[Effective C++ 정리 #10] 대입 연산자의 return *this의 의미?!
이 글은 『Effective C++』를 읽고 개인적으로 공부한 내용을 정리한 기록입니다.
저는 컴퓨터공학을 전공하지 않았으며, 프로그래밍을 공부하는 과정에서의 이해와 생각을 정리하기 위해 글을 작성하고 있습니다.
따라서 내용 중 일부에 오류나 부정확한 설명이 있을 수 있으며, 피드백은 언제든지 환영합니다. 확인 후 수정하도록 하겠습니다.
전문적인 해설이 아닌 개인적 시선에서의 정리임을 참고하고 읽어주시면 감사하겠습니다.
[Effective C++ 정리 #10] 대입 연산자는 항상 *this를 반환하라
C++에서 연산자 오버로딩을 구현할 때, 특히 operator=
같은 대입 연산자를 다룰 땐 반환값으로 *this
를 참조 형태로 리턴하는 것이 관례입니다. 이것은 단순한 스타일이 아니라, 문법과 기능적인 측면 모두에서 매우 중요한 역할을 합니다.
왜 꼭 return *this;
를 써야 할까?
C++에서는 다음과 같은 코드를 자주 보게 됩니다:
int x, y, z;
x = y = z = 15; // 연쇄 대입(chain assignment)
이 코드는 다음과 같이 해석됩니다:
x = (y = (z = 15));
즉, 오른쪽부터 왼쪽으로 값이 대입되면서, 각 대입 연산자는 결과로 대입된 왼쪽 값을 반환합니다. 이 패턴은 기본 타입뿐 아니라, 사용자 정의 타입에도 동일하게 적용되길 기대합니다.
그렇기 때문에 우리는 다음처럼 구현해야 합니다:
class Widget {
public:
Widget& operator=(const Widget& rhs) {
...
return *this; // 자기 자신을 참조로 반환
}
};
이렇게 해야 다음 코드도 자연스럽게 작동하죠:
Widget a, b, c;
a = b = c; // 연쇄 대입
이 규칙은 +=, -= 같은 연산자에도 적용된다
operator+=
, operator-=
등 복합 대입 연산자도 동일한 규칙을 따릅니다:
class Widget {
public:
Widget& operator+=(const Widget& rhs) {
...
return *this;
}
Widget& operator=(int value) { // 매개변수가 다른 경우에도
...
return *this;
}
};
즉, 매개변수 타입이 정수이든 객체이든 상관없이, 모든 대입 연산자는 자신을 참조로 반환하는 것이 표준입니다.
꼭 따라야 하나요?
이건 강제되는 문법은 아닙니다. 즉, void operator=(const T& rhs)
처럼 void로 작성해도 컴파일은 됩니다. 하지만 그렇게 하면 위에서 말한 연쇄 대입이나 표준 라이브러리 호환성에서 문제가 발생할 수 있다고 합니다.
C++ 표준 라이브러리의 모든 타입들(e.g. std::string
, std::vector
, std::shared_ptr
)도 이 규칙을 따르기 때문에, 따라서 사용자 정의 타입도 같은 방식으로 동작해야 일관성을 유지할 수 있습니다!
핵심 요약
- 모든 대입 연산자는
*this
를 참조 형태로 반환해야 한다.
감사합니다.