Effective C++/More Effective C++
[More Effective C++] 6. operator++ / operator--
김디트
2024. 8. 6. 11:25
728x90
항목 6 : 증가 및 감소 연산자의 전위 / 후위 형태를 반드시 구분하자
++, -- 연산자 오버로드 규칙의 필요성
- 80년대 후반에는 전위, 후위 방식으로 호출하는 것을 구분할 방법이 없었다.
- 그래서 해당 연산자의 전위 / 후위 형태를 오버로딩 할 수 있도록 스팩이 향상되었다.
- 근데 오버로딩은 보통 매개변수의 타입에 따라 구분되는데?
- 증감 연산자는 인자를 전혀 받지 않는다는 문제가 있다.
- 그래서 아래의 규칙이 생겨났다.
증감 연산자의 오버로딩 규칙
- 후위 형태는 int 타입의 인자를 받는다.
- 증감 연산자가 후위로 호출될 때 컴파일러는 해당 인자로 0을 넘겨준다.
- 전, 후위 형태는 서로 다른 타입을 반환한다.
- 전위 형태
- 참조자 타입을 리턴
- 후위 형태
- const 객체 타입을 리턴
- 전위 형태
class UPInt
{
public:
UPInt& operator++(); // 전위 ++
const UPInt operator++(int); // 후위 ++
UPInt& operator--(); // 전위 --
const UPInt operator--(int); // 후위 --
UPInt& operator+=(int); UPInt와 int에 대한 +=
...
};
UPInt i;
++i; // i.operator++() 호출
i++; // i.operator++(0) 호출
--i; // i.operator--() 호출
i--; // i.operator--(0) 호출
전, 후위 연산자의 반환값이 다른 이유
- 연산자의 용법이 다르기 때문이다.
- 전위 형태
- 증가시키고 값을 사용한다.(increment and fetch)
- 후위 형태
- 값을 사용하고 증가시킨다.(fetch and increment)
- 전위 형태
UPInt& UPInt::operator++() // 전위 형태
{
*this += 1; // 증가시킨다.
return *this; // 값을 가져온다.
}
const UPInt UPInt::operator++(int) // 후위 형태
{
// 매개변수 int는 사용하지 않는다.
// 그저 전, 후위를 구분하기 위한, 오버로드 구분용이기 때문이다.
// 이름이 붙은 매개변수는 사용하지 않으면 경고가 나올 수 있으므로,
// 이름을 생략해 버렸다.
const UPInt oldValue = *this; // 값을 가져온다.
++(*this); // 증가시킨다.
return oldValue; // 저장해둔 값을 반환한다.
}
- 헌데 왜 후위 연산자의 리턴값은 const여야 할까?
- 기본 제공(built-in) 타입 증가 연산자의 동작과 일치시키기 위함이다.
- 클래스를 설계할 때, "아리송하면 int의 동작원리대로 만들어라"
- 사용자가 직관적으로 이해하지 못할 동작을 원천 차단시켜야 한다.
- 기본 제공(built-in) 타입 증가 연산자의 동작과 일치시키기 위함이다.
UPInt UPInt::operator++(int); // const가 빠진 후위 연산자
UPInt i;
// 후위 증가 연산자를 두 번 적용한다.
i++++; // i.operator++(0).operator++(0); 과 같은 코드
////////////////////////
// 기본 제공 타입의 경우
int ri;
ri++++; // 컴파일 에러 발생!
////////////////////////
// 또한 const 빠진 후위 연산자를 그대로 사용하면
i++++; // i의 값은 한 번만 증가한다.
// 첫 번째 ++연산자의 반환값 : 값이 증가하기 전의 임시객체
// 두 번째 ++연산자는 값이 증가하기 전의 임시객체에 대해 값을 증가시키므로.
// 이는 i의 값이 두 번 증가하리라 예상하는 사용자의 직관과 다르다.
후위 연산자의 비효율성
- 반환값으로 쓰기 위한 임시 객체가 필요하다.(항목 19 참조)
- 심지어 해당 임시 객체는 지역 변수로서 생겼다가 없어지는 것이다.
- 그러므로 전위 / 후위를 비교하면 전위 연산자가 효율적이다.
전, 후위 연산자의 동작이 동일하다는 보장
- 전, 후위 연산자는 반환 타입을 제외하면 하는 일이 같다.
- 그러므로 시간이 지나더라도 동작 방식을 보장하기 위해서는..
- 후위 증감 연산자는 반드시 전위 증감 연산자를 사용해서 구현하도록 하자.
참조
[Effective C++] 18. 인터페이스 설계
항목 18. 인터페이스 설계는 제대로 쓰기엔 쉽게, 엉터리로 쓰기엔 어렵게 하자 제대로 쓰기엔 쉽고 엉터리로 쓰기엔 어려운 인터페이스 개발사용자가 저지를만한 실수의 종류를 머리에 넣
delightlane.tistory.com
728x90