C++ Return value optimization. 리턴값 최적화

함수에서 객체를 리턴하면 어떻게 될까?

분명 학부때는 머릿속에 잘 정리해놨던 부분인데 연차가 길어지면서 점점 모호해졌고,
그래서 가능하면 객체 리턴은 지양해왔습니다.
이참에 한번 제대로 정리해놓고자 합니다.

함수 내 객체 소멸

함수 내에서 생성한 객체는 함수가 소멸하는 시점에 함께 삭제됩니다.
그렇게 삭제될 객체를 리턴한다?
리턴해서 복사하는 변수와 삭제될 객체 사이의 애매한 시점으로 인해 문제가 생기지 않을까 하는 불안감이
머릿속에서 정리되지 않아서 점점 사용을 피하게 되었습니다.

Return Value Optimization

물론 이러한 저의 우려와 다르게 이미 이 부분에 대해서 문제없도록
컴파일러에서 최적화가 잘 되어있습니다.

실행 결과입니다.

1
2
3
4
% clang++  rvo.cpp
% ./a.out
constructor
c1=1

returnC1 함수 내의 c1 객체를 리턴해서 받아주는 변수가 있다면?
함수내의 c1은 삭제되어야하고 리턴받는 c1은 copy 해야하고
이 모호함을 해결할뿐만 아니라 copy 해야하는 부하까지 제거하는 최적화가 잘 되어있네요.
위의 코드에서 copy contructor가 호출되지 않는다는 것으로 확인할 수 있습니다.

-fno-elide-constructors

최적화를 끄는 옵션도 있을거라 찾아보니 있네요.

1
2
3
4
5
6
% clang++ -fno-elide-constructors  rvo.cpp
% ./a.out
constructor
copy constructor
copy constructor
c1=1

copy constructor가 호출되는 것을 확인할 수 있습니다.

모든 컴파일러가 그러한가?

그럴것 같습니다.
대충 찾아봐도 1993 g++ 컴파일러에도 옵션이 있어서 더이상 찾아볼 필요성을 못느꼈습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
man pages for g++
GNU Tools Last change: 30apr1993
...
-felide-constructors
Use this option to instruct the compiler to be smarter
about when it can elide constructors. Without this
flag, GNU C++ and cfront both generate effectively the
same code for:

A foo ();
A x (foo ()); // x initialized by `foo ()', no ctor called
A y = foo (); // call to `foo ()' heads to temporary,
// y is initialized from the temporary.

Note the difference! With this flag, GNU C++ initial-
izes `y' directly from the call to foo () without going
through a temporary.

출처 : man pages for g++ 30apr1993

Share