[C++] 복사 생성자와 RVO, NRVO
01. 복사 생성자란?
- 같은 타입의 인스턴스를 매개변수로 받는 생성자를 의미한다.
class A
{
public:
A() {};
A(const A& a){}; // Copy Constructor
};
02. 복사 생성자가 호출되는 경우
복사 생성자가 호출되는 경우는 세 가지이다.
- 기존 생성 객체를 사용해 새로운 객체를 초기화하는 경우
- Call-By-Value 형식으로 함수의 매개변수를 전달할 때
- Value 형태로 함수에서 return할 때
A origin;
// 1.
A copy(origin);
A copy1 = origin;
// 2.
void Copy(A a)
{
// do something
}
// 3.
A Copy2()
{
return A();
}
그렇다면, 아래 코드의 결과는 어떨까?
#include <iostream>
class A
{
public:
A()
{
std::cout << this << " Constructor Called\n";
}
A(const A& a)
{
std::cout << this << " Copy Constructor Called\n";
}
~A()
{
std::cout << this << " Destructor Called\n";
}
};
A Copy(A origin)
{
return A(origin);
}
int main()
{
A origin;
A c1 = Copy(origin);
}
위에서 말한 복사 생성자 호출 조건에 따르면 복사 생성자는 총 3번 불려야 한다.
- Copy() 함수의 매개변수 origin이 생성되며 한 번
- return값으로 전달되는 임시 객체를 생성하며 한 번
- c1의 복사 생성자가 호출되며 한 번
그러나 실제로 Visual Studio로 실행해보면 Copy Constructor는 두 번 호출된다. 이는 RVO라는 컴파일러 최적화 기법 때문이다.
RVO (Return Value Optimization)은 C++11부터 공식화된 기능으로, 불필요한 복사를 컴파일러가 최소화한다.
RVO가 적용되면 위 코드에서 복사 생성자가 호출되는 부분은 다음과 같다.
- Copy() 함수의 매개변수 origin이 생성되며 한 번
- return값으로 전달되는 임시 객체를 생성하며 한 번
c1은 리턴되는 임시 객체의 주소를 바로 참조하게 된다.
NRVO (Named Return Value Optimization)은 말 그대로 Named, 함수 스코프 안에서 이름이 있는 임시 객체가 반환될 때에도 최적화를 수행하는 것이다.
즉, 위의 Copy함수가 아래와 같은 형태더라도 최적화를 수행해준다.
A Copy(A origin)
{
A copy(origin);
return copy;
}
NRVO는 최적화 옵션 /O1부터 동작한다고 하는데... 잘 모르겠지만 비주얼 스튜디오 기준으로 Release모드에서 적용된다.
반환값 최적화 RVO, NRVO
클래스 내에서 어떤 객체를 반환하고 싶다. 하지만 반환되는 과정의 오버헤드가 두려울 수 있다. 1 2 3 4 std::string get_name() const { return std::string(my_name); } 일단 저 구문을 보면 이렇게..
zepeh.tistory.com
Rvalue 와 RVO, NRVO
C/C++를 써야만 하는 혹은 쓸 수 밖에 없는 상황들이라는 것은 대부분 성능,속도, 자원 사용의 최적화 등이지요. Visual Studio 2010에 새로이 추가된 Rvalue concept 이나 사용 예들도 정확히 이러한 상황
egloos.zum.com