함수에서 객체 반환시 참조로 X(effective c++ 21)

2015. 8. 23. 01:25프로그래밍/Effective C++

728x90
728x90

참조에 의한 전달

모든 경우에서 참조에 의한 전달만을 사용하려고 해서는 안 된다.


문제점
‘값에 의한 전달’에 숨겨진 효율 문제를 알아챈 후에, 나머지 모든 부분에서 
‘참조에 의한 전달’만을 사용하려 할 경우 문제가 생긴다.
실제로 있지도 않은 객체의 참조자를 넘기려는 상황이 올 수도 있다.

새로운 객체를 반환

operator*가 참조자를 반환하도록 만들어졌다면, 
이 함수가 반환하는 참조자는 반드시 이미 존재하는 Rational 객체의 참조자여야 한다.

문제점
참조자는 존재하는 객체에 붙는 ‘또 다른’ 이름이다.
반환될 객체에 대한 참조자를 operator*에서 반환할 수 있으려면, 그 객체를 직접 생성해야 한다.
함수 수준에서 새로운 객체를 만드는 방법은 2가지이다.( 스택에 생성, 힙에 생성 )

스택에 만드는 방법



생성자를 호출하는 것이 싫어서 작성한 것인데 결국 result가 다른 객체처럼 생성된다.

이 연산자 함수는 result에 대한 참조자를 반환하는데, result는 지역 객체이다. 함수가 끝날 때 소멸된다.

이 operator*는 온전한 Rational 객체에 대한 참조자를 반환하지 않는다.


힙에 만드는 방법



new로 할당한 메모리를 초기화 할 때 생성자가 호출된다.

new로 생성한 객체이기 때문에 어디선가 delete를 해 주어야 하는데 삭제 시점을 알 수 없다.


정적으로 만드는 방법
스레드 안정성 문제가 얽혀 있다. 비교시에 문제점이 생길 수 있다.

해결법



반환 값을 생성하고 소멸시키는 비용이 든다. 그러나 여기에는 올바르게 동작하기 위해 작은 비용을 들인다.

최적화 메커니즘에 의해 operator*의 반환 값에 대한 생성과 소멸 동작이 안전하게 제거될 수 있다.

( 반환 값 최적화 : return value optimization, 줄여서 RVO 라고 부른다 )


정리
지역 스택 객체에 대한 포인터나 참조자를 반환하는 일, 혹은 힙에 할당된 객체에 대한 참조자를 반환하는 일 또는 지역 정적 객체에 대한 포인터나 참조자를 반환하는 일은 그런 객체가 두 개 이상 필요해질 가능성이 있다면 절대로 하지 말자.


728x90
반응형