본문 바로가기

STUDY/C++

전위(prefix) vs 후위(postfix) 증감연산자

우리는 증감연산자를 오버로딩할 때 다음과 같이 정의합니다.

 

class Point
{
public:
	Point& operator++();				//전위++
	const Point operator++(int);			//후위++

private:
	int _value;

};

 

전위는 인자가 없고, 후위는 증감연산자가 호출될 때 0을 넘기도록 하는 것입니다. 

이보다 더 중요한 것은 전위형태는 참조자 타입을 반환하고, 후위 형태는 const 객체타입을 반환합니다. 

 

보통 사람들은 전위형태"증가시키고 값을 사용하는" 연산자이고, 후위 형태"값을 사용하고 증가시키는" 연산자로 외우고 있을 것입니다.  c++ 스펙에서 공식적으로 이렇게 설정되어 있습니다. 

 

 

class Point
{
public:
	Point() :_value(0) {};

	// 1. 전위 증가 
	Point& operator++()				
	{
		this->_value += 1;  // 1. 증가
		return *this;		// 2. 값을 가져옵니다. 
	};

	// 2. 후위 증가
	const Point operator++(int)
	{
		const Point temp = *this;		// 1. 값을 가져옵니다. 
		this->_value += 1;				// 2. 증가
		return temp;					// 미리 가져온 값을 반환합니다.
	};

private:
	int _value;

};

 

위의 후위 연산자 구현을 보면 이상한 모습을 하고있습니다. 

일단 첫번째로는 받은 매개변수를 사용하고 있지 않습니다. 매개변수는 그저 전위와 후위를 구별하기 위한 것입니다.

매개변수를 사용하지 않으면 경고 메시지를 띄우는 컴파일러도있기 때문에, 아예 이름이 없는 매개변수를 사용합니다.

 

후위증가 연산자는 증가되기 전의 객체를 반환해야 하는것은 스펙이므로 납득이 가지만 왜 const여야 할까요? 

const가 아니라면 다음과 같은 코드도 가능하게 됩니다. 

 

Point p;

p++++;

 

하지만 이 코드는 다음과 같습니다.

 

point.operator(0)++.operator++(0);

 

두번째부터 호출되는 operator는 전혀 의미가 없게 됩니다. 임시객체에 대해서 ++연산을 하게 될 테니까요. 

증가연산자의 이상동작을 야기하지 않기 위해서 const로 꼭 해주어야 합니다. 

 

 

두번째로는 사용하지 않는 임시객체를 만들어내고 있습니다. 

실행 효율을 따지면 후위 연산자는 사용하지도 않는 임시객체를 계속해서 만들어 내고 있는 셈이니 정말 효율적이지 않습니다.

전위연산자를 권장하는 이유도 다음과 같은 이유에서 일 것입니다. 

 

저도 후위 연산자를 버릇처럼 사용하는 일이 잦았는데 앞으로는 꼭 전위연산자를 사용해야 겠습니다.