Table of Contents
전위 연산자 ++i, 후위 연산자 i++
원래부터 진짜 필요한 곳이 아니면 후위 연산자 대신 전위 연산자를 쓰라. 성능과 메모리에 모두 영향을 준다.는 건 알고 있었지만 코딩 테스트 문제 풀면서 크게 영향을 준 케이스가 있어서 생각난 김에 정리.
그냥 프로그래밍 언어의 기본 중의 기본인 전위 연산자와 후위 연산자에 대한 짤막한 상식을 이야기해볼까 한다.
코드 한 줄을 수행할 때, 전위 연산자는 i에 1을 우선적으로 더하고 같은 코드 내의 작업을 수행하고, 후위 연산자는 코드 내의 작업을 수행하고 i에 1을 더한다.
다들 여기까지는 알지만, ++i와 i++을 시행할 때 C++에서 실제로 어떻게 동작할까?는 많이 알지 못한다.
연산자 오버로딩
C++은 연산자 오버로딩의 개념이 있다. 연산자를 개발자가 직접 정의할 수 있도록 하는 것이다. 연산자는 이런 것들이 있다.( i+=1, i>n, i*n, i/n, ++i, i– 등등)
위 연산자들도 결국엔 클래스의 메소드나 함수로 정의되는 것이다. 여기서 이 연산자 오버로딩을 언급하는 이유는 전위 연산자와 후위 연산자의 동작 차이 때문이다.
전위 연산자는 인자가 되는 그 자체 Object에 값을 더해주고 자체 Object를 반환하면 끝이다. 하지만 후위 연산자는 새로운 Object를 생성하고, 인자가 되는 Object에 값을 더해주고 새로 생성한 Object을 반환시켜 주어야 한다.
왜? 그것이 후위 연산자니까. 작업을 모두 수행한 이후에 1을 더해주는 기능을 하는 것이니. 작업을 모두 수행하기 위해 복사본이 필요하다. 아래 Counter 클래스의 전위 후위 연산자를 보면 좀 이해가 될 것이다.
class Counter {
public:
int value;
Counter(int val) : value(val) {}
// 전위 증가 연산자
Counter& operator++() {
++value; // 값을 증가
return *this; // 증가된 값을 참조로 반환
}
// 후위 증가 연산자
Counter operator++(int) {
Counter temp = *this; // 현재 값을 복사하여 임시 저장
++value; // 값을 증가
return temp; // 증가 전의 값을 반환
}
};
후위 연산자인 Operator++(int)를 보면 현재 Object를 복사하는 행위를 볼 수 있다. 큰 Object일수록 후위 연산자의 성능이 극도로 나빠질 수 있는 이유다. 일반 자료형인 int나 long 정도는 컴파일러가 어떻게든 최적화를 해주지만 사용자 클래스의 최적화 까지는 기대하기 어렵다.
사례) leetcode Valid Palindrom
전위 연산으로 풀었을 때와 후위 연산으로 풀었을 때의 차이. 런타임이 눈에 띄게 개선된 것을 볼 수 있다!
결론: 웬만하면 전위 연산자를 쓰자.
진짜로 후위 연산자가 필요한 기능이 아닌 이상 전위 연산자를 쓰자. 일단 전위 연산자로 쓰는 습관을 가지자. 그리고 후위 연산자로 바꾸자. 전위 연산자가 메모리와 속도 모두 월등히 빠르다.
답글 남기기