[ Effective C++ ] 항목 21 : 함수에서 객체를 반환해야 할 경우에 참조자를 반환하려 들지 말자

Minsu._.Lighting·2023년 11월 25일
0

[ Effective C++ ] 정리 모음집
" C++ 프로그래머의 필독서, 스콧 마이어스의 Effective C++ 를 읽고 내용 요약 / 정리 "

[핵심]

" 모든 코드는 오직 '참조자에 의한 전달' 만으로 이루어져야 한다는 생각을 버리자! "

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

💡 객체 반환, 참조자 반환 둘 중에 어떤걸 쓰지?

  • 어떤 선택을 하든 올바른 동작이 이루어지도록 만들어야 한다!


💡 참조자를 반환할 때 생기는 문제들..

  • 참조자는 존재하는 객체의 또 다른 이름이다.
    - 참조자를 반환하기 위해서는 객체가 존재해야 한다

📌 예시 1, 스택에서 객체 생성 후 참조자 반환

[operator* 코드]

const Rational& operator*(const Rational& lhs, const Rational& Rhs)
{
	Rational result(lhs.n * rhs.n, lhs.d * rhs.d);
    return result;
}
  • 생성자를 생성하기 싫어서 참조자를 반환하게 한건데 결국엔 객체를 생성해야 한다...

  • result는 스택에서 생성된 지역객체 이므로 함수가 종료되면 소멸한다!
    - 이미 소멸한 객체가 있던 공간을 가리키는 곳을 반환해버리는 꼴...

📌 예시 2, 힙 에서 객체 생성 후 참조자 반환

[operator* 코드]

const Rational& operator*(const Rational& lhs, const Rational& Rhs)
{
	Rational* result = new Rational(lhs.n * rhs.n, lhs.d * rhs.d);
    return *result;
}
  • 예시 1과 마찬가지로 생성자가 호출된다..

  • new로 동적 할당 된 메모리는 언제, 누가 해제해 줄 것인가..?
    📢 Rational w, x, y, z; • • • w = x * y * z;
    - operator* 호출이 두 번 일어났기에 new 와 delete도 두 번 일어나야 한다.
    - x * ( y * z )의 참조자는 접근할 수 있어도, y * z 연산 후 반환된 참조자에는 접근할 수 없다...
    => 메모리 누출이 일어난다!

📌 예시 3, 정적 객체 생성 후 참조자 반환

[operator* 코드]

const Rational& operator*(const Rational& lhs, const Rational& Rhs)
{
	static Rational result;
  
	result = lhs.n * rhs.n, lhs.d * rhs.d;
    return result;
}
  • 마찬가지로 생성자가 호출된다.

  • 또 다른 문제 발생!
    Rational a, b, c, d;
    if((a*b) == (c*d));
    - operator*의 결과 값은 정적(static)객체인 result 이기 때문에 위 if 조건문은 항상 true가 된다...

📌 올바른 코드

[operator* 코드]

inline const Rational& operator*(const Rational& lhs, const Rational& Rhs)
{
    return Rational(lhs.n * rhs.n, lhs.d * rhs.d);
}
profile
오코완~😤😤

0개의 댓글

관련 채용 정보