Search Results for 'MEC++'

1 POSTS

  1. 2008/02/04 i++보다 ++i가 더 빠르다? (1)

More Effective C++ C++에서 postfix보다 prefix가 더 빠르다는 말이 있습니다. 결론을 먼저 말하자면, 어떤 경우에는 맞는 말이고 다른 경우에는 그렇지 않습니다. 사실, 이는 MEC++항목 6에서 다루고 있는 주제입니다. 책에 나온 내용 말고는 얻을게 없으므로, 읽어보신 분은 skip하심 되겠습니다. :-)

저는 몇년전에 후위연산자보다 전위연산자가 더 빠르다는 말을 처음 들었을 때에, 도저히 이해하지 못했습니다. 제가 이해하지 못한 이유는, 컴파일된 어셈 코드가 ++i 쪽이 빠르다고 들었기 때문이죠. 지금 생각해보면, 이것은 상당한 오해였습니다. 당시에 Visual C++ 6.0에서 만들어진 어셈코드를 비교하면서, 멋대로 전위 연산자가 더 빠르다고 믿어버렸는데, 사실 어셈코드의 차이는 그것때문이 아니었습니다. 이에 대해 설명하기 시작하면 너무 장황해지므로 생략하고요.. 에, 또, Accelerated C++의 예제들에서도 별 다른 설명 없이 전위연산자를 선호했기 때문에 오해가 증폭된 점도 있었습니다만.

전위연산자든 후위연산자든 증가하려는 i라는 인스턴스가, char, int, double 따위의 내부 타입이라면, 속도는 다르지 않습니다. 실제로 몇몇 컴파일러들에서 컴파일을 하고 디스어셈블을 때려보면, 같은 코드가 나옵니다.

하지만, i가 객체의 인스턴스라면 얘기가 달라집니다. MEC++에 나오는 예제를 사용하겠습니다.

04: class UPInt {
05: public:
06:     UPInt& operator++();
07:     const UPInt operator++(int);
08: };

 

여기에서 참조를 반환하는 6번째 줄의 operator++()가 전위연산자이고, const을 반환하는 7번째 줄의 operator++(int)는 후위연산자입니다. 이 모습을 보면 3가지 의문점이 듭니다.

  1. 왜 후위연산자는 int 타입의 argument가 있는가?
  2. 후위연산자의 리턴타입은 왜 const인가?
  3. 전위연산자의 리턴은 참조인데, 후위연산자는 왜 값인가?

첫번째는, 단순히 함수를 구분하기 위함입니다. -_-; C++에서 호출될 함수를 구분하는 것은, 함수의 이름과 매개변수타입 말고는 없지요. 이거 뭐.. 언어 제약 안에서 힘겹게 저런 이상한 모습을 창조해낸 분들이 참 불쌍하게 느껴집니다.

두번째는, i++++ 같은 모양을 막기 위함입니다. i++의 결과가 참조라면, i++++ 이라고 해도 문법상 틀린 부분이 없습니다. i.operator++(0).operator++(0) 과 같은 말이거든요. C++은 int타입에 대해서 후위 증가 연산자를 두번 쓰는 것을 금하고 있기 때문에, 우리들의 클래스에서도 맞춰주는 쪽이 좋겠지요. 게다가 i++++ 이라고 하더라도, 2가 증가하지 않고 실제로는 1만 증가하게 될 수 있습니다. i++의 결과에서 ++를 하는 것인데, i++의 결과 자체가 일단 i의 값이잖아요.

마지막으로, 가장 중요한 부분입니다. 전위연산자는 참조를 리턴하는데, 후위연산자는 왜 값을 리턴하는가? 이 부분은 C++ 스펙에 공식적으로 설정된 모양새를 봐야합니다.

10: UPInt& UPInt::operator++()
11: {
12:     *this += 1;
13:     return *this;
14: }
15: 
16: const UPInt UPInt::operator++(int)
17: {
18:     const UPInt oldValue = *this;
19:     ++(*this);
20:     return oldValue;
21: }

 

보다시피, 후위연산자는 현재의 값을 리턴한 후에, 증가를 하는 특수한 작동방식으로 인해서, 구현상 내부에서 복사생성(18번줄)을 하게 됩니다. 저 클래스의 생성에 오버헤드가 별로 없다면 모르지만, 클래스의 크기가 커지면 좀 곤란하겠지요. 후위연산자로 ++를 할때마다 복사생성을 할테니깐요!

그래서.. 그래서, i가 클래스의 인스턴스인 경우는, ++i가 i++보다 빠를 수 밖에 없습니다. 정리하자면, 증가하는 인스턴스가,

  • 내부 타입의 경우는, 속도가 같습니다.
  • 객체인 경우는, postfix가 더 빠릅니다.

C++은 보면 볼수록, 땜빵을 수없이 해버린 언어라는 느낌이 들곤 합니다. 일관성이 결여된 부분도 은근히 많고, 좀 지저분하달까요. C++로 코딩을 하다보면 로직을 위한 부분보다는, 언어의 제약을 벗어나기 위한 꽁수가 더 많아지는 것 같기도 합니다. -_-;; 뭐, 그래도.. 템플릿과 STL이 있어서 참 좋지만...

-- Jong10

꼬랑지. ++Jong10 이란 블로그가 있다면, 저보다는 미묘하게 빠르겠군요?! =_=