별빛의 낙하지 :: [C++0x] Move Constructor

[C++0x] Move Constructor

C++ 2012. 11. 15. 23:38 Posted by byulbit
/*
	Move Constructor( 이동 생성자 )

	c++0x 에는 r-value reference의 도입으로 인해서 Move Constructor가 생겼다.
	이동 생성자의 특징은 복사 대상의 데이터를 지우는 소유권 이전 방식이다.

	기존에 있던 reference는 그래서 이름이 l-value reference 로 불린다.
	l-value 와 r-value 의 차이는 대입식에서 왼쪽에 오느냐, 오른쪽에 오느냐의 차이인데
	
	간단히 말해서 l-value 는 변수라고 보면 되고, r-value는 상수라고 보면 된다.
	기존에 l-value reference는 l-value들만, 즉 변수들만 가리킬 수 있는 반면에
	r-value reference는 r-value 들만, 즉 상수들을 가리킬 수 있다.
	
	int b = 3;
	int& a = b;
	int& c = 3; // error
	
	int&& d = a; // error
	int&& d = 3; // ok.

	r-value reference가 사실 그냥 보기에는 이동 생성자와 전혀 무관해 보이는데, 이것은 기존에
	복사 생성자로 표현하기 어색했던, 소유권 이전방식을 적절히 표현하기에 적합하다.

	무슨 말이냐면,  기존에 auto_ptr 과 같은 소유권 이전의 스마트 포인터들은 값을 이동시키고 싶어하지만,
	적절한 표현이 없어서, const를 제외시킨 아래와 같은 방식으로 구현을 했었다.

	auto_ptr(auto_ptr& a)
	
	문제는 이것이 복사하려는 것인지, 이동하려는 것인지에 대한 명확한 지표가 되기 힘들다는 것.
	이 문제를 해결한 것이 r-value reference(&&)의 등장이다.
r
*/

#include 

class MoveClass
{
public:
	// Default Constructor
	MoveClass() {
		std::cout << "Default Constructor Call" << std::endl;
	}
	
	// Copy Constructor
	MoveClass(const MoveClass& a)	// 반드시 const로 해야 된다. 그렇지 않으면 Move Constructor가 제대로 호출되지 않는다.  
	{
		std::cout << "Copy Constructor Call" << std::endl;				

	}

	// Move Constructor
	MoveClass(MoveClass&& a)
	{
		std::cout << "Move Constructor Call" << std::endl;

	}
};


// 값이 복사되는 곳에서는 일반적으로 복사 생성자가 호출된다.
MoveClass foo(MoveClass& a)
{
	MoveClass local;
	return local;		// 값이 복사 되는데, 우선순위가 존재한다.
						// MoveClass(const MoveClass& a) 형태의 복사 생성자가 존재하고,
						// MoveClass(MoveClass&& a) 형태의 이동 생성자가 존재하면
						// 이동 생성자를 호출한다.
}

int main()
{
	MoveClass a;	// Default Constructor Call

	foo(a);

	MoveClass b(a);					// Copy Consturctor call
	MoveClass b(std::move(a));		// Move Constructor call

}