일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
Tags
- 반복자
- reference
- 영화 리뷰
- Vector
- 언리얼
- 상속
- lua
- 티스토리챌린지
- Effective c++
- UE4
- 영화
- 루아
- 오블완
- 메타테이블
- resource management class
- exception
- implicit conversion
- 다형성
- 스마트 포인터
- Smart Pointer
- effective stl
- 참조자
- 암시적 변환
- operator new
- virtual function
- 예외
- 게임
- more effective c++
- c++
- 비교 함수 객체
Archives
- Today
- Total
스토리텔링 개발자
[More Effective C++] 6. operator++ / operator-- 본문
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 참조)
- 심지어 해당 임시 객체는 지역 변수로서 생겼다가 없어지는 것이다.
- 그러므로 전위 / 후위를 비교하면 전위 연산자가 효율적이다.
전, 후위 연산자의 동작이 동일하다는 보장
- 전, 후위 연산자는 반환 타입을 제외하면 하는 일이 같다.
- 그러므로 시간이 지나더라도 동작 방식을 보장하기 위해서는..
- 후위 증감 연산자는 반드시 전위 증감 연산자를 사용해서 구현하도록 하자.
참조
728x90
'개발 > More Effective C++' 카테고리의 다른 글
[More Effective C++] 8. new / delete 연산자와 operator new / delete (0) | 2024.08.08 |
---|---|
[More Effective C++] 7. operator&& / operator|| / operator, (0) | 2024.08.07 |
[More Effective C++] 5. 암시적 변환 지양하기 (0) | 2024.08.05 |
[More Effective C++] 4. 불필요한 기본 생성자 미제공하기 (0) | 2024.08.04 |
[More Effective C++] 3. 다형성 객체의 배열 지양하기 (0) | 2024.08.03 |
Comments