[R value] 임시 객체 (temporary object) - ChoiChiWon/ccw GitHub Wiki

임시 객체 (temporary object)

  • 이름이 없으며 stack memory에 잡히는 object
  • 일반 object와는 달리 해당 라인의 세미 콜론을 만나면 파괴되는 속성을 가진다.

임시객체 pointer

  • 해당 라인의 연산이 끝나고 파괴되는 속성이 있기 때문에 object의 주소값을 포인터 변수에 저장하는 것이 불가능하다.
foo p;  // 일반 object

foo *p1 = &p;   // ok
foo *p2 = &foo();   // error

임시 객체 와 rvalue

  • 임시 객체는 rvalue에 해당된다.
  • lvalue는 value가 사용되는 expression을 넘어서도 생존하는 값인데 반해 rvalue는 이름이 없고 해당 value가 사용되는 expression을 넘어서면 생존하지 않는 값이다.
foo p;

p.x = 1;  // ok
foo().x = 10;  // error

임시 객체와 reference

  • 임시 객체는 해당 라인이 끝나면 파괴되기 때문에 일반 object처럼 reference를 가지는게 불가능하다.
  • 언제 파괴될지 모르는 object의 주소를 참조하는다는 것은 위험한 코드이다.
  • 하지만 const reference는 허용된다.
  • 임시 객체의 reference 정보를 const 참조 변수에 넘기면 임시 객체의 lifetime은 연장된다.
  • 하지만 const reference이기 때문에 값의 변경은 불가능하다.
  • rvalue reference에 대해서도 성립된다.
foo p;   // 일반 object

foo& ref = p;   // ok
foo& ref2 = foo();   // error
const foo& ref3 = foo();   // ok
foo&& ref4 = foo();   // ok

임시객체 parameter Passing

  • function call시에 parameter passing을 효율적으로 수행할 수 있다.
// 함수 foo의 parameter로 일반 object를 넘기는 예제

void foo(TmpClass p)
{
   cout << "call foo" << endl;
}

void main()
{
   TmpClass p;
   foo(p);     // 일반 object를 parameter로 넘긴다.
   cout << "main end" << endl;
}

// 실행 결과
TmpClass 생성자 호출
TmpClass의 복사 생성자 호출
call foo
TmpClass 소멸자 호출
main end
TmpClass 소멸자 호출
  • parameter를 const 참조로 넘길 경우 임시 객체를 생성하지 않으므로 복사 생성자와 소멸자 호출이 없다.
void foo(const TmpClass& p)
{
   cout << "const reference call" << endl;
}

void main()
{
   foo(TmpClass());   // 임시 객체로 넘긴다.
   cout << "main end" << endl;
}

// 실행 결과
TmpClass 생성자 호출
const reference call
TmpClass 소멸자 호출

임시객체 return value : RVO

TmpClass foo()
{
   TmpClass p();
   return p;        // 임시 객체가 생성되어 return
}

void main()
{
   TmpClass p1();
   p1 = foo();
   cout << "end" << endl;
}

// 실행 결과
TmpClass 생성자 호출
TmpClass 생성자 호출
TmpClass 복사 생성자 호출
TmpClass 소멸자 호출
TmpClass 소멸자 호출
end
TmpClass 소멸자 호출
  • 함수 foo의 return 값 반환 과정에서 임시 객체가 생성되면서 복사 생성자가 호출되고, 값을 반환한 뒤 파괴된다.
TmpClass foo()
{
    return TmpClass();    // RVO
}

void main()
{
   TmpClass p1();
   p1 = foo();
   cout << "end" << endl;
}

// 실행 결과
TmpClass 생성자 호출
TmpClass 생성자 호출
TmpClass 소멸자 호출
end
TmpClass 소멸자 호출
  • 임시 객체를 생성과 동시에 return하여 return용 객체의 복사생성자와 소멸자 호출이 일어나지 않는다.
  • 이런 return 기법을 Return Value Optimization(RVO)라고 한다.

참고 사이트

Lvalues and Rvalues (C++)
C++ Object Lifetimes
Temporary object lifetime - cppreference