함수에서 객체 반환시 참조로 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
반응형
'프로그래밍 > Effective C++' 카테고리의 다른 글
타입변환이 모든 매개변수에 적용된다면? 그 함수는 비멤버로(effective c++ 24) (0) | 2015.08.25 |
---|---|
멤버 함수보단 비멤버 비프렌드 함수를!(effective c++ 23) (0) | 2015.08.25 |
데이터 멤버는 private(effective c++ 22) (0) | 2015.08.25 |
클래스 설계는 타입 설계와 같이 보자(effective c++ 19) (0) | 2015.08.20 |
인터페이스 설계방법. 제대로는 쉽게, 엉터리론 어렵게(effective c++ 18) (0) | 2015.08.20 |
new로 생성한 객체를 스마트포인터에 저장하는 코드는 별도의 한 문장(effective c++ 17) (0) | 2015.08.20 |
new/delete 형태 맞추기(effective c++ 16) (0) | 2015.08.20 |