일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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
- 예외
- effective stl
- 상속
- 스마트 포인터
- 게임
- 참조자
- implicit conversion
- 메타테이블
- exception
- resource management class
- 언리얼
- more effective c++
- lua
- 티스토리챌린지
- 반복자
- UE4
- Effective c++
- c++
- virtual function
- 루아
- 비교 함수 객체
- 암시적 변환
- operator new
- reference
- 영화 리뷰
- Smart Pointer
- Vector
- 오블완
- 다형성
- 영화
Archives
- Today
- Total
스토리텔링 개발자
[More Effective C++] 22. 대입 형태 연산자 선호하기 본문
728x90
항목 22 : 단독 연산자(op) 대신에 =이 붙은 연산자(op=)를 사용하는 것이 좋을 때가 있다.
사용자가 기대하는 연산자 동작
// 아래의 연산자가 동작한다면,
x = x + y;
x = x - y;
// 아래의 연산자도 동작한다고 기대하게 된다.
x += y;
x -= y;
- 하지만 사용자 정의 타입이라면 위의 두 형태의 코드가 지원되리라는 보장은 전혀 없다.
- C++에서는 operator+, operatr=, operator+= 사이에 아무 관계가 없다.
- 즉, 사용자의 기대를 충족시키려면 구현하는 수밖에 없다.
대입 형태(operator+=)와 단독 형태(operator+) 관계 맺기
- 대입 형태를 사용해서 단독 형태를 구현하는 것도 괜찮은 방법이다.
class Rational
{
public:
...
Rational& operator+=(const Rational& rhs);
Rational& operator-=(const Rational& rhs);
};
// operator+=를 사용해서 구현
// 반환값이 const인 이유(항목 6 참조)
const Rational operator+(const Rational& lhs,
const Rational& rhs)
{
return Rational(lhs) += rhs;
}
// operator-=를 사용해서 구현
// 반환값이 const인 이유(항목 6 참조)
const Rational operator-(const Rational& lhs,
const Rational& rhs)
{
return Rational(lhs) -= rhs;
}
- 해당 형태의 장점
- 대입 형태만 유지보수 해주면 된다.
- 위의 예제처럼, 대입 형태의 연산자가 public이라면?
- 단독 형태의 연산자를 클래스의 프렌드(friend)로 만들지 않아도 된다.
템플릿을 써서 단독 형태 연산자를 자동 생성하기
- 단독 형태 연산자를 모두 전역 유효 범위(global scope)에 두어도 괜찮다면 선택 가능한 방법.
- 클래스 안에 단독 형태의 연산자 함수를 구현할 필요성을 없앨 수 있다.
template<typename T>
cosnt T operator+(const T& lhs, const T& rhs)
{
return T(lhs) += rhs;
}
template<typename T>
cosnt T operator-(const T& lhs, const T& rhs)
{
return T(lhs) -= rhs;
}
// 위 템플릿과 타입 T에 대한 대입 형태 연산자만 준비되어 있다면
// 단독 형태 연산자는 자동으로 만들어진다.
대입 형태와 단독 형태 연산자의 효율에 대한 팁
1. 대입 형태 연산자가 보통 더 효율적이다.
2. 대입 형태와 단독 형태 연산자를 모두 제공하면, 사용자는 효율 / 편리성 둘을 가늠해서 취사선택할 수 있다.
Rational a, b, c, d, result;
// 방법 1
// operator+당 임시 객체가 발생한다.(임시 객체 3개)
// 허나 작성과 디버깅, 유지보수에 이점이 있다.
result = a + b + c + d;
// 방법 2
// 임시 객체가 발생하지 않는다.
// 하지만 디버깅과 유지보수에는 적합하지 않다.
rasult = a;
result += b;
result += c;
result += d;
3. 단독 형태 연산자를 구현할 때 이름 없는 임시 객체가 더 효율적임을 인지하고 있도록 하자.
// 방법 1
template<typename T>
const T operator+(const T& lhs, const T& rhs)
{
return T(lhs) += rhs; // 이름 없는 임시 객체(lhs의 복사본)를 반환한다.
}
// 방법 2
template<typename T>
const T operator+(const T& lhs, const T& rhs)
{
T result(lhs); // result에 lhs를 복사한다.
return result += rhs; // result를 반환한다.
}
- 동일하게 동작할 것 같아보이나 두 번째 방법은 약간 더 비효율적이다.
- 반환되는 객체가 이름 있는 객체라는 사실은, 컴파일러에 따라 반환값 최적화(항목 20 참조)가 동작하지 않는다는 것을 의미한다.(최소한 구 버전 컴파일러는 그렇다.)
- 하지만 첫 번째 방법은 항상 RVO(반환값 최적화, Return Value Optimization)가 항상 먹히는 코드이다.
728x90
'개발 > More Effective C++' 카테고리의 다른 글
[More Effective C++] 24. 다형성의 비용 (0) | 2024.09.03 |
---|---|
[More Effective C++] 23. 적절한 라이브러리 선택하기 (0) | 2024.09.02 |
[More Effective C++] 21. 오버로딩으로 암시적 변환 막기 (0) | 2024.08.28 |
[More Effective C++] 20. 반환값 최적화(return value optimization) (0) | 2024.08.27 |
[More Effective C++] 19. 임시 객체(temporaries) (0) | 2024.08.26 |
Comments