일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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
- c++
- 영화 리뷰
- exception
- operator new
- more effective c++
- 암시적 변환
- UE4
- resource management class
- 언리얼
- Effective c++
- 메타테이블
- 상속
- virtual function
- 게임
- 오블완
- Smart Pointer
- 예외
- reference
- 반복자
- 비교 함수 객체
- 루아
- 참조자
- lua
- 다형성
- 영화
- 함수 객체
- implicit conversion
- 티스토리챌린지
- effective stl
- 스마트 포인터
Archives
- Today
- Total
스토리텔링 개발자
[More Effective C++] 20. 반환값 최적화(return value optimization) 본문
개발/More Effective C++
[More Effective C++] 20. 반환값 최적화(return value optimization)
김디트 2024. 8. 27. 10:52728x90
항목 20 : 반환값 최적화(return value optimization)가 가능하게 하자.
객체를 값으로 반환하는 함수
- 리턴할 때 임시 객체의 생성 및 소멸이 필수적으로 발생한다.(항목 19 참조)
- 그렇다면 객체를 반환하지 않으면 발생하지 않을 비용이겠군.
- 하지만 반드시 객체를 반환하지 않으면 안되는 함수도 있다.
// 유리수
class Rational
{
public:
Rational(int numerator = 0, int denominator = 1);
...
int numerator() const;
int denominator() const;
};
// 유리수에 대해 곱셈을 해주는 함수
// 반환값이 const여야 하는 이유는 항목 6 참조
const Rational operator*(const Rational& lhs, const Rational& rhs);
- operator*는 객체를 반드시 반환해야 하는 함수이다.
- 이 경우, 반환값을 위한 임시 객체를 안 만들래야 안 만들 수가 없다..
반환값을 값 대신 포인터로?
// 값 리턴을 피하기 위해 포인터를 리턴하는 함수
// 하지만 별로 안 좋은 방법..
const Rational* operator*(const Rational& lhs, const Rational& rhs);
Rationa a = 10;
Rational b(1, 2);
Rational c = *(a * b); // 너무나 부자연스러운 용법이기 때문이다.
// 더군다나 반환한 포인터 리소스 관리는 누가 할 것인가?
// 삭제를 안 해주면 리소스 누수인데..
반환값을 값 대신 참조자로?
// 참조자를 반환하는 방법.
// 하지만 불가능한 방법이다.
const Rational& operator*(const Rational& lhs, const Rational& rhs)
{
Rational result(lhs.numerator() * rhs.numerator(),
lhs.denominator() * rhs.denominator());
// 범위를 벗어나면 소멸되는 객체를 참조자로 리턴한다?
return result;
}
Rational a = 10;
Rational b(1, 2);
Rational c = a * b; // 문법 상으로는 어색하지 않지만..
반환값 최적화(return value optimization : RVO)
- 안타깝지만 객체를 값 반환하는 함수의 '값 반환' 부분은 수정할 방도가 없다.
- 그러므로 리턴 객체의 비용을 줄이는 것에 만족해야 한다.
- 애초에 반환되는 객체의 비용이 없다면 값 반환 임시 객체를 없애려고 전전긍긍할 필요도 없다.
- 즉, 값 반환을 하지만 임시 객체의 비용이 들지 않는 함수를 추구하자.
- 그 방법은, 객체 대신 생성자 인자를 반환하는 것이다.
const Rational operator*(const Rational& lhs, const Rational& rhs)
{
// 생성자를 사용해 임시 Rational 객체를 만든다.
// 즉, 지역 객체 대신 생성자 인자를 반환한다.
return Rational(lhs.numerator() * rhs.numerator(),
lhs.denominator() * rhs.denominator());
}
Rational a = 10;
Rational b(1, 2);
Rational c = a * b; // 이 경우 컴파일러 최적화의 여지가 있다.
// operator* 안에서 생기는 임시 객체, operator*가 반환하는 임시 객체를 모두 없애고
// 계산 결과값을 객체 c 메모리에 직접 넣어 초기화를 해준다.
- 대부분의 컴파일러는 위와 같은 컴파일러 최적화 기능을 갖추고 있다.
- 이를 반환값 최적화(return value optimization : RVO)라고 한다.
- 여기서 조금 더 최적화를 하자면..
- c는 이름이 붙은 객체인데, 이름이 붙은 객체는 컴파일러 최적화 혜택을 받을 수 없다.(항목 22 참조)
- 하지만 operator*를 인라인 함수로 선언하면 이에 대한 오버헤드를 없앨 수 있다.
-
inline const Rational operator*(const Rational& lhs, const Rational& rhs){ ... }
728x90
'개발 > More Effective C++' 카테고리의 다른 글
[More Effective C++] 22. 대입 형태 연산자 선호하기 (0) | 2024.08.30 |
---|---|
[More Effective C++] 21. 오버로딩으로 암시적 변환 막기 (0) | 2024.08.28 |
[More Effective C++] 19. 임시 객체(temporaries) (0) | 2024.08.26 |
[More Effective C++] 18. 과도 선행 평가 (0) | 2024.08.23 |
[More Effective C++] 17. 지연 평가 (0) | 2024.08.22 |
Comments