문제를 풀다보면 누구는 전위 연산자(++i)를 사용하고, 누구는 후위 연산자(i++)를 자주 사용한다.
처음 코딩 공부할 때 전위 연산자를 사용해서 프로그램을 만들었다가 호되게 당한적이 있어서,
보다 예측이 쉬운 후위 연산자를 즐겨 사용했었는데 컴퓨터 구조, 운영 체제를 공부하다가 한 가지 고민이 생겼다.
전위 연산자와 후위 연산자의 동작과 연산 속도에 차이가 있지 않을까?
이러한 의문이 들었던 것은 C++ 클래스에서 전위/후위 연산자를 생성하는 로직을 보고 난 이후부터 였다.
class Cl {
int attr;
public:
...
Cl& operator++ ();
Cl& operator++ (int x);
}
// 전위 연산자
Cl Cl::operator++() {
++attr;
return *this;
}
// 후위 연산자
Cl Cl::operator++(int x) {
Cl tmp = *this;
++attr;
return tmp;
}
전위 연산자와 달리
후위 연산자는 매개변수가 추가가 되며, 결정적으로 현재 인스턴스를 참조하는 복사 생성자를 필요로 한다.
그렇다면 성능 차이가 존재하지 않을까?
- 기본 타입의 경우, 연산자가 내장되어 있으므로 컴파일러가 코드를 최적화할 수 있으므로 C언어처럼 성능 차이가 존재하지 않는다.
- C++ 클래스의 인스턴스라면, operator++(int) 함수는 복사본을 생성해야 하는데 이는 컴파일러가 최적화할 수가 없으므로 복사 비용이 클 수록 성능에 큰 영향을 미친다.
- 다만, James Sutherland는 경우에 따라서는 후위 연산자 또한 최적화될 수 있음을 보여주고 있다.
- 이유가 없다면 전위 연산자를 사용하는 것이 가장 안전하다. (전위 연산자가 더 빠르다는 보장은 없지만, 느릴 일은 없다)
솔직히 코테 하면서 클래스 생성할 일이 얼마나 되겠냐마는,
최근엔 전위 연산자 쓰는 게 좀 더 폼 나길래 전위 연산자를 자주 쓰고 있다.
기본 타입을 사용할 때는 큰 성능 차이를 볼 수 없다고 하지만 습관이라는 게 중요한 거니까, 전위 연산자를 좀 더 애용해보려고 노력 중이다.
🧐 자바에서는 어떨까?
C++의 어마어마한 속도에 반해서 비록 코테는 C++을 사용하지만, 어쨌든 내 주 언어는 자바이므로 궁금해서 찾아봤다.
- 자바에서 후위 연산자를 사용하면, 변수가 증가되기 전의 값을 임시 보관하기 때문에 약간의 성능 차이가 발생한다.
- 하지만 "단독 문장으로" 사용할 때는 약간의 성능 차이 외엔 별다른 효과를 보기가 힘들다. (너무 미세해서 하나마나)
- for문에서는 조건식, 증감식이 따로 실행되므로 딱히 차이가 없다.
- while문으로 루프할 때는 조건식과 증감식이 동시에 실행되므로 차이가 발생한다.
- 하지만 이것도 컴파일러가 최적화를 해주냐 안 해주냐에 따라 차이가 없을 수도 있다.
갑자기 궁금해져서 찾아봤는데 제법 재밌는 내용들이어서 즐거웠다.
특히, 예전과는 달리 컴파일러에 대한 이해도가 늘어서인지 막힘없이 답변들을 읽을 수 있었다.