On this page
article
C++ Temporary Object
임시 객체 (Temporary Object)
- 정의: 이름 없는 객체. 보통
{}
초기화나 반환값으로 생성. - 수명: 선언된 라인에서 소멸 (단, 참조로 바인딩되면 수명 연장).
Point {1, 2}; // unnamed temporary object
- Value Category:
prvalue
(pure rvalue) → 좌변에 올 수 없고, 주소 연산자 (&
) 사용 불가. - 수명 연장 방법:
const lvalue reference
로 바인딩 시 연장됨.rvalue reference
로도 바인딩 가능.
const Point& r2 = Point{1,1}; // 수명 연장
Point&& r3 = Point{1,1}; // 수명 연장
- 활용: 함수 인자 전달 시 매우 유용.
void draw_line(const Point& from, const Point& to);
draw_line(Point{0, 0}, Point{30, 30}); // 임시 객체 전달
복사 생략 (Copy Elision)
- 정의: 복사 생성자 호출 없이 객체를 직접 생성하는 컴파일러 최적화.
- 예시:
Point pt = Point{1, 2}; // 복사 생략 (C++17부터는 보장)
- C++17 이전: 최적화 여부는 컴파일러에 따라 다름. 복사 생성자가 삭제되거나 private이면 에러 발생 가능.
- C++17 이후: Guaranteed Copy Elision → 문법적으로 복사 생략.
임시 객체 물질화 (Temporary Materialization)
- 정의: 특정 상황에서만 임시 객체가 실제 메모리에 생성되는 과정.
개념
- **임시 객체 물질화(Temporary Materialization)**는 prvalue(순수 rvalue) 표현식이 실제 메모리에 객체로 생성되는 과정을 의미합니다.
- C++에서는 모든 prvalue가 항상 객체가 되는 게 아니라, 필요할 때만 실제 객체가 메모리에 생성됩니다.
prvalue는 언제 물질화되는가?
참조로 바인딩될 때:
- prvalue를 const lvalue reference나 rvalue reference로 바인딩할 경우 임시 객체가 물질화됩니다.
const Point& r = Point{1, 2}; // 물질화 + 수명 연장 Point&& r2 = Point{3, 4}; // 물질화 + 수명 연장
Object로 초기화될 때:
- prvalue를 object로 초기화할 때 물질화됩니다.
Point p = Point{1, 2}; // 물질화
값을 무시하는 경우 (discarded-value expression):
- 단순히
{}
로 초기화만 하고 결과를 사용하지 않으면 물질화되지 않습니다.
Point{1, 2}; // 물질화 X (discarded-value expression)
- 단순히
C++17의 변화
- C++17 이전:
{}
로 생성한 prvalue는 대부분 물질화되어 임시 객체가 생성됩니다. - C++17 이후: prvalue는 표현식만 존재하고, 실제 메모리상의 객체가 필요할 때만 물질화됩니다. 메모리 효율이 향상됨.
예시로 살펴보기
struct Point { int x, y; };
// 1. 물질화되지 않음 (discarded-value expression)
Point{1, 2};
// 2. 물질화됨 (object로 초기화)
Point p1 = Point{1, 2};
// 3. 물질화됨 (참조로 바인딩)
const Point& p2 = Point{1, 2};
참조 한정자 (Reference Qualifier)
- 정의: 멤버 함수 뒤에
&
또는&&
을 붙여 lvalue/rvalue 객체에 따라 호출될 멤버 함수를 구분하는 문법.
class X {
public:
void f1() & { std::cout << "lvalue\n"; } // lvalue 객체에서 호출
void f1() && { std::cout << "rvalue\n"; } // rvalue 객체에서 호출
};
- 예시:
X obj;
obj.f1(); // lvalue → "lvalue"
X{}.f1(); // rvalue → "rvalue"
의미:
void f1() &
→X&
타입의 객체를 위한 함수.void f1() &&
→X&&
타입의 객체를 위한 함수.
활용 예시: Getter와 Move:
class StringWrapper {
std::string data;
public:
std::string& get() & { return data; } // lvalue
const std::string& get() const & { return data; } // const lvalue
std::string&& get() && { return std::move(data); } // rvalue
};
이렇게 하면 lvalue에서는 복사로, rvalue에서는 move로 가져올 수 있다.