Copy Elision(RVO와 NRVO)

Naezan·2024년 4월 19일

C++

목록 보기
2/5

Copy Elision

Copy elision은 컴파일러가 복사 생성자나 이동 생성자를 호출하지 않고 객체를 직접 생성하는 최적화 기술로 C++11표준에 공식화되었습니다. 간단한 예시는 아래와 같습니다.

Copy Elision 범용적인 코드

// https://en.wikipedia.org/wiki/Copy_elision 참고
struct C 
{
	explicit C(int) {}
	C(const C&) { std::cout << "Hello World!" << endl; }
};

int main()
{
	C c1(5);      // 생성자 호출
	C c2 = C(5);  // 복사 생성자 호출
}

위 코드에서 C c1은 생성자를 호출하고 c2는 복사 생성자를 호출하게 되는데, 실제로는 Copy elision에 의해 복사 생성자가 아닌 생성자가 호출됩니다. 물론 컴파일러에 따라 최적화하지 않은 상태로 복사생성자가 호출되는 경우도 있습니다.

RVO

Return Value Optimization의 약자로 함수가 객체를 반환하기 위해 생성된 임시 객체를 제거하는 컴파일러 최적화입니다. 불필요한 복사 생성을 제거해주는 복사 제거(copy elision) 의 한 형태로 볼 수 있습니다.

RVO 예시 코드

class MyObject {
public:
    MyObject() { std::cout << "Constructor called\n"; }
    MyObject(const MyObject& other) { std::cout << "Copy constructor called\n"; }
    ~MyObject() { std::cout << "Destructor called\n"; }
};

MyObject createObject() {
    return MyObject();
}

위 코드에서 createObject() 함수는 MyObject의 객체를 반환하게 되는데, RVO가 적용되지 않는다면 이 함수가 호출될 때 임시객체가 생성되게 됩니다. 그리고 그 임시 객체가 복사 또는 이동되어 전달될 것입니다. 그러나 최적화가 적용되면, 컴파일러는 createObject()가 반환하는 객체를 직접 생성(생성자의 호출)할 수 있습니다.

NRVO

Named Return Value Optimization의 약자로 RVO와 유사하지만 함수 내에서 객체를 생성한 후 해당 임시 객체를 반환할때, 해당 임시객체를 제거하고 바로 생성자를 호출해주는 최적화 기법입니다.

NRVO 예시 코드

class MyObject {
public:
    MyObject() { std::cout << "Constructor called\n"; }
    MyObject(const MyObject& other) { std::cout << "Copy constructor called\n"; }
    ~MyObject() { std::cout << "Destructor called\n"; }
};

MyObject createObject() {
	MyObject obj;
    return obj;
}

위의 코드에서 createObject()는 함수 내에서 obj 객체를 생성하고, 이 객체를 바로 반환합니다. 이때 NRVO가 적용되어 컴파일러는 임시 객체(obj) 를 생성하지 않고, 함수 내에서 만든 obj 객체를 호출자에 직접 반환하게 됩니다.

Copy elision을 사용하게되면(아마도 대부분 적용되어 있음) 불필요한 복사 생성자 호출과 임시객체 생성 비용을 줄이고 성능을 향상시킬 수 있습니다.

참고자료
https://en.wikipedia.org/wiki/Copy_elision
https://stackoverflow.com/questions/12953127/what-are-copy-elision-and-return-value-optimization

profile
게임 개발자

0개의 댓글