전위 연산자와 후위 연산자의 경우 오버로딩할 원함수의 함수명은 같다.
하지만 반환값과 파라미터가 다른데,
전위 연산자(Prefix Operator)의 경우 파라미터를 받지않고 래퍼런스를 반환하고
후위 연산자(Postfix Operator)의 경우 int 타입을 파라미터로 전달받고 객체를 반환한다.
전위 연산자는 연산자를 호출한 직후에 바로 값이 바뀌어야하고
후위 연산자는 연산자를 호출하고, 연산이나 대입 후 값이 바뀌어야하기 때문이다.
따라서 후위연산자를 오버로딩 할 때는 this 포인터를 이용한 객체를 반환하는 게 아닌, 바뀌기 전 값을 가지고있는 다른 객체를 반환해야한다.
전위 연산자의 경우 컴파일러는 operator++(), operator--()를 호출하고,
후위 연산자의 경우 컴파일러는 operator++(0), operator--(0)를 호출한다.
파라미터로 더미 값인 int값 0을 전달하여 이름이 같은 전위 연산자와 후위 연산자를 구분하여 호출할 수 있게 되는 것이다.
#include <iostream>
class MyInt{
public :
MyInt(int val) : _val(val), _myName("origin"){}
MyInt &operator++(){
_val += 1;
return (*this);
} //전위 연산자
MyInt operator++(int){
MyInt temp(_val);
temp._myName = "temp";
_val += 1;
return (temp);
} //후위 연산자
int _val;
std::string _myName;
};
std::ostream& operator <<(std::ostream& outputStream, const MyInt& obj);
int main(){
MyInt a(2);
std::cout << ++a << std::endl; //*1
std::cout << a++ << std::endl; //*2
std::cout << a << std::endl;
}
std::ostream& operator <<(std::ostream& outputStream, const MyInt& obj){
std::cout << "my name is " << obj._myName << " : " << obj._val;
return outputStream;
}
1 라인에서 호출한 operator <<는 파라미터로 this 포인터로 반환받은 a객체를 전달받게된다.
2 라인에서 호출한 operator <<는 파라미터로 값이 바뀌기 전의 a를 copy한 temp를 전달받게된다.
output >
my name is origin : 3
my name is temp : 3
my name is origin : 4
후위 연산자의 경우 복사본을 만들어야하는 경우가 있어 전위 연산자보다 연산을 더 많이 하는 경우가 생긴다.
(전위 연산자가 후위 연산자보다 오랜 시간이 걸리는 경우는 없다!!)
하지만 int, char 같은 기본 타입들은 사실 속도에 차이점이 없다.
하지만 후위 연산자를 써야하는 특별한 이유가 있는 것이 아니면 전위 연산자를 사용하는 것을 권유하고있다.
📖 Overloading operators
📖 Which is more efficient: i++ or ++i