Computer >> 컴퓨터 >  >> 프로그래밍 >> C++

C++ 복사 생략(Copy Elision)과 반환 값 최적화(RVO) 완벽 정리

복사 생략(Copy Elision)은 대부분의 컴파일러가 구현하고 있는 최적화 기법으로, 특정 상황에서 불필요한(그리고 잠재적으로 비용이 큰) 객체 복사를 방지하는 역할을 합니다.

예를 들어, 생성된 객체가 실제로 사용되지 않거나 부작용(side effect)이 없는 코드가 있다면, 컴파일러는 해당 객체를 아예 생성하지 않고 건너뛸 수 있습니다.

예제 코드

struct MyStruct {
    MyStruct() {}
    MyStruct(const MyStruct&) {
        std::cout << "Copied.\n";
    }
};
MyStruct f() {
    return MyStruct();
}
int main() {
    std::cout << "Main\n";
    MyStruct obj = f();
}

실행 결과

컴파일러와 빌드 설정에 따라 다음과 같은 출력 중 하나를 얻을 수 있습니다.

Main

Main
Copied
Copied

Main
Copied

복사 생략이 주는 시사점

위 결과에서 알 수 있듯이, 실제로 생성되는 객체의 수는 개발자가 예상하는 것보다 적을 수 있습니다. 즉, 특정 횟수만큼 생성자나 소멸자가 호출된다는 보장을 할 수 없습니다.

따라서 다음 사항을 반드시 기억해야 합니다.

  • 복사 생성자(copy constructor), 이동 생성자(move constructor), 소멸자(destructor) 안에는 반드시 실행되어야 하는 핵심 로직을 넣지 마세요.
  • 리소스 해제, 카운터 감소, 로깅 등 호출 횟수에 의존하는 동작은 예기치 않게 생략될 수 있습니다.

C++17부터는 이름 없는 임시 객체(prvalue)에 대한 복사 생략이 언어 표준으로 강제되었으며, 이를 '보장된 복사 생략(guaranteed copy elision)'이라고 부릅니다. 덕분에 함수에서 객체를 값으로 반환하더라도 불필요한 복사 없이 곧바로 대상 위치에 객체가 생성됩니다.

결론적으로, 복사 생략과 RVO(Return Value Optimization, 반환 값 최적화)는 프로그램 성능을 크게 향상시킬 수 있는 유용한 최적화이지만, 객체의 생성·소멸 횟수에 의존하는 코드를 작성할 때는 주의해야 한다는 점을 기억하세요.