개발자 면접 공부/C-C++

RVO vs NRVO

chogyujin 2023. 5. 11. 18:41
728x90

오늘은 RVO 랑 NRVO 대해서 알아보도록 하겠습니다.


1. 개요

RVONRVO함수에서 C++ 객체지향을 어떻게 하면 빠른 속도와 컴파일러단에서 부터 코드를 최적화 시켜서 더욱 빠르고 정확하게 실행 할 수 있는지에 대한 내용입니다.

 

대표정으로 RVO 와 NRVO 가 있습니다.
RVO = Return Value Optimization
NRVO = Named Return Value Optimization

 


2. RVO VS NRVO

#include<iostream>
#include<algorithm>
#include<vector>

using namespace std;
class A
{
private:
	string s;
public:
	A(string s) : s(s)
	{
		cout <<s<< " 초기 생성자" << endl;
	}
	A(const A& a)
	{
		this->s = a.s;
		cout <<s<< " 복사 생성자" << endl;
	}
	A(const A&& a)
	{
		this->s = a.s;
		
		cout <<s<< " 이동 생성자" << endl;
	}
	~A()
	{
		cout <<s<< "소멸자" << endl;
	}
};

/**NRVO*/
A makeA(string name)
{
	A a(name);
	return a;
}

/**RVO*/
A makeA2(string name)
{
	return A(name);
}

int main()
{
	A a1 = makeA("a1");
	A a2 = makeA2("a2");
	return 0;
}

이러한 형태를 가지고 있습니다. 이런경우 어떻게 호출순서가 되면

  1. A a1 에서 makeA 함수를 R-Value 형태로 return 값을 받기위해 함수진입
  2. makeA에서 파라미터로 받은 name을 A a(name) 객체를 생성후 생성자호출
  3. return a 를통해 객체에 이동생성자를 불러 임시 객체를 만들고 소멸자를 콜
  4. a1에 할당
  5. a2는 makeA2 함수를 R-Value 형태로 return 값을 받기위해 함수진입
  6. 들어가는 동시에 return을 통해 생성자만 호출 후 반환
  7. a2에 할당

이를 통해 RVO 가 NRVO보다 좀더 속도가 빠르고 굳이 임시객체에 할당을 할 필요가 없다는 사실을 알았습니다.

하지만 이 모드는 Visual Studio에서 Debug모드로 실행했을때에 결과이며

Release 모드로 실행하면 다음과 같은 현상이 발생합니다.

이게 무슨일인가여??

사실 Release 모드는 Visual Studio에서 컴파일러 상에서 스스로 최적화를 위해 RVO로 변환하여 컴파일을 하기 때문입니다.

A = 다음의 우측값으로 넣을 필요 없이 바로 A에 대입하면 된다는것을 컴파일러가 인지하고 최적화를 하기 때문입니다.


3. 요약

  1. 최적화를 위해 RVO를 사용하는것이 좋다 NRVO는 괜히 임시 객체를 만들어 시간이 더 소모된다.
  2. 하지만 Visual Studio에서는 자체적으로 최적화를 시키는 Release 모드가 있다.
  3. 왜냐하면 Release모드는 최종 배포하는 모드이기 떄문에 컴파일러가 더욱 신경을 써주는거 같다.