증감 연산자 prefix, postfix 차이

Mark Lee·2021년 11월 30일
0

C++

목록 보기
2/2

통상 증감(increment/decrement) 연산자(operator)를 사용할 때, ++i형태를 자주 사용하게 됩니다.
그리고 나오는 이슈가 "++ii++의 차이가 무엇이냐"입니다.
결과적으로는 차이가 없습니다. 둘 다 i에 1을 더할 뿐입니다.

하지만, 좀 더 상세하게 보면,
이 둘은 연산자 자체가 구분됩니다.

아래는 마이크로소프트 문서에 정의된 예시입니다.
https://docs.microsoft.com/ko-kr/cpp/cpp/increment-and-decrement-operator-overloading-cpp?view=msvc-170

prefix increment operator가 위에서 ++i인 경우이고,
postfix increment operator는 i++인 경우입니다.

// Define prefix increment operator.
Point& Point::operator++()
{
   _x++;
   _y++;
   return *this;
}

// Define postfix increment operator.
Point Point::operator++(int)
{
   Point temp = *this;
   ++*this;
   return temp;
}

prefix를 보면 단순히 숫자에 1을 더해서 포인터를 넘겨주지만,
postfix에서는 새로운 객체를 생성한 다음에, prefix operator를 호출하고 객체를 전달합니다. 그래서 일반적으로 ++i가 빠르다고 얘기합니다.

하지만 이건 어디 까지나 일반적인 class에 해당되는 내용이며, double, int와 같은 primitive variable에 해당되지 않습니다. 왜냐면 compiler에서 알아서 i++++i의 형태로 처리하기 때문입니다.

테스트를 해보겠습니다.

아래 코드는 단순하게 크기가 1억인 vector를 만들고 이를 for문으로 순회(traverse)하는 코드입니다.
첫 번째는 단순히 index로 순회를 하였고 i++로 순회를 하였고, 두 번째는 ++i로 순회를 했습니다.
세 번째/네 번째는 iterator를 사용해서 순회를 했고 역시 it++++it방식으로 구분을 했습니다.

위의 말이 맞다면, int로 정의된 index의 순회는 i++, ++i의 차이가 없어야 하며, iterator클래스를 사용한 경우인 it++에서 복사가 일어나므로 더 느려야 합니다.

std::vector<int> test(100000000, 0);
size_t sz = test.size();

std::chrono::high_resolution_clock::time_point tt0 = std::chrono::high_resolution_clock::now();

for(int i=0;i<sz;i++ )
{

}
std::chrono::high_resolution_clock::time_point tt1 = std::chrono::high_resolution_clock::now();

for(int i=0;i<sz;++i )
{

}
std::chrono::high_resolution_clock::time_point tt2 = std::chrono::high_resolution_clock::now();

int cnt =0;
for(auto it=test.begin();it!=test.end();it++ )
{

}

std::chrono::high_resolution_clock::time_point tt3 = std::chrono::high_resolution_clock::now();

cnt =0;
for(auto it=test.begin();it!=test.end();++it)
{

}

std::chrono::high_resolution_clock::time_point tt4 = std::chrono::high_resolution_clock::now();

auto ts0 = std::chrono::duration_cast<std::chrono::milliseconds>(tt1 - tt0).count();
auto ts1 = std::chrono::duration_cast<std::chrono::milliseconds>(tt2 - tt1).count();
auto ts2 = std::chrono::duration_cast<std::chrono::milliseconds>(tt3 - tt2).count();
auto ts3 = std::chrono::duration_cast<std::chrono::milliseconds>(tt4 - tt3).count();

std::cout << ts0 <<"\n";
std::cout << ts1 <<"\n";
std::cout << ts2 <<"\n";
std::cout << ts3 <<"\n";

시간을 찍어보면 다음과 같습니다.

176
179
1347
945

조금 차이는 있지만, 첫 번째와 두 번째는 거의 비슷합니다.
반대로 iterator를 쓴 경우는 ++it가 조금 더 빠른 것을 볼 수 있습니다. 누구나 다 알만한 내용을 한번 테스트 해보았습니다.

여기서 중요한 건, 쓸데없이 순회 목적으로 vector iterator를 쓰지 말라는 점 정도가 되겠네요.

profile
C++/C#, Python을 주로 사용하는 개발자입니다. Engineering 알고리즘 개발을 주 업무로 하고 있습니다.

0개의 댓글