for
루프 내에서 ++i
와 i++
의 차이는 전위 증가(prefix increment) 연산자와 후위 증가(postfix increment) 연산자의 차이입니다.
결론부터 말하면, for
루프의 조건식(i < arr.size()
)이 단순하고 반복 횟수가 많지 않은 대부분의 경우에는 성능상 차이가 거의 없습니다. 하지만 복잡한 타입이나 객체를 대상으로 할 때는 분명한 성능 차이가 발생할 수 있으며, 일반적으로 ++i
를 사용하는 것이 더 효율적입니다.
++i
)동작: 먼저 피연산자 i
를 1 증가시킨 후, 증가된 값을 반환합니다.
**저수준 동작 (의사 코드):**C++
int& operator++() { // T& operator++()
// 1. 값 증가
this->value += 1;
// 2. 증가된 자신의 값(참조) 반환
return *this;
}
특징: 추가적인 변수나 임시 객체를 만들 필요가 없습니다. 단순히 값을 변경하고 그 주소를 반환하므로 매우 효율적입니다.
i++
)동작: 먼저 피연산자 i
의 원래 값을 임시 저장소에 보관한 후, 피연산자 i
를 1 증가시키고, 보관해두었던 원래 값을 반환합니다.
**저수준 동작 (의사 코드):**C++
int operator++(int) { // T operator++(int)
// 1. 현재 값(old_value)을 임시 저장소에 복사
int old_value = this->value;
// 2. 값 증가
this->value += 1;
// 3. 임시 저장해 둔 원래 값을 반환
return old_value;
}
특징: 원래 값을 반환하기 위해 임시 객체를 생성하고 복사하는 오버헤드가 발생합니다.
for
루프에서의 차이for (int i = 0; i < arr.size(); ++i)
for (int i = 0; i < arr.size(); i++)
이 두 루프는 i
가 1씩 증가하는 for
루프의 셋째 부분에서 사용됩니다. 이 부분의 반환값은 for
루프의 동작에 영향을 주지 않습니다.
컴파일러는 i
가 기본 타입(int
)일 때, i++
가 i
의 원래 값을 반환하더라도 그 반환값을 사용하지 않는다는 것을 알고 있습니다. 따라서 대부분의 현대적인 컴파일러는 ++i
와 i++
를 동일한 기계어 코드로 최적화합니다.
하지만, i
가 복잡한 타입이나 클래스 객체일 경우(예: 이터레이터), 상황은 달라집니다.
iterator++
: 후위 증가 연산자는 임시 객체를 복사하고 반환하는 과정을 거치므로 iterator
객체의 복사 생성자가 호출됩니다.++iterator
: 전위 증가 연산자는 iterator
객체 자체를 수정하고 참조를 반환하므로 임시 객체 생성 및 복사 과정이 없습니다.따라서 이터레이터처럼 복잡한 타입의 객체를 다룰 때는 ++i
가 i++
보다 성능상 더 효율적인 것이 명확합니다.