-
NRVO는 프로젝트 속성 페이지의 C/C++의 최적화 탭에서 최적화 항목을 최적화라고 선택해야 동작합니다. 속도 우선이나 크기 우선 옵션으로 해도 됩니다. 최적화 옵션을 키고 나서 RTC1 옵션과 충돌을 일으킨다는 메시지가 뜨면 C/C++의 코드 생성 탭에서 기본 런타임 검사 옵션을 기본값으로 설정합니다. NRVO가 동작하면 다음 코드는 객체 복사를 수행하지 않습니다.
#include <iostream> using namespace std; class Test { public: Test() : _num(0) { cout << "Constructor" << endl; } Test(int num) : _num(num) { cout << "Constructor : " << _num << endl; } Test(const Test& rhs) { cout << "Copy " << rhs._num << " >> " << _num <<endl; _num = rhs._num; } Test(Test&& rhs) noexcept { cout << "Move " << rhs._num << " >> " << _num << endl; _num = rhs._num; } ~Test() { cout << "Destructor : " << _num << endl; } friend ostream& operator<<(ostream& os, Test& t) { return os << "overloading " <<t._num; } private: int _num; }; Test func() { Test t; return t; } int main() { Test t = func(); }
RVO는 임시 객체를 반환하거나 함수의 파라미터로 넘기면 객체 복사를 수행하지 않는 것입니다. 이 부분의 코드는 생략하겠습니다.
다음 코드를 수행하면 로그가 어떻게 나올까요? t1, t2 객체는 어차피 함수 종료와 함께 소멸되므로 move 함수로 리턴해줘야 할까요?
Test testFunc() { Test t1(1); Test t2(2); int i = 0; cin >> i; if (i < 0) return t1; else return t2; } int main() { Test result = testFunc(); cout << "---------------" << endl; cout << result << endl; }
컴파일러는 알고 있습니다. 그래서 자동으로 move 생성자를 호출해줍니다. 여기서 신기한 점은, 아직 정확한 이유는 파악하지 못했습니다만, result 객체에 1이 할당되어 있다는 점입니다. 중단점을 찍어 보면 if(i < 0) 분기를 타고 들어갑니다. 로그에는 안 나왔지만 t1의 값이 들어가있는 것으로 추정됩니다. 어셈블리 파일을 봤지만 아직은 제대로 된 이유를 모르겠습니다.
중요한 부분은 move 생성자를 컴파일러가 알아서 호출해줬다는 것입니다.
'개발 > C·C++' 카테고리의 다른 글
shared_ptr 사용할 때 주의 사항 (0) 2022.01.09 전달 참조(보편 참조) (0) 2022.01.08 constexpr (0) 2022.01.06 noexcept (0) 2022.01.06 객체 생성 시 const의 위치 차이 (0) 2022.01.04