C++11에 와서 가장 큰 변화점 중 하나가 RValue와 이동 생성자의 지원이라 할수 있을 것 같습니다. C++11 이전에는 컨테이너에 객체를 삽입 한다고 하면, 보통 객체를 복사해 컨테이너에 삽입 되는 형식이었습니다.

class Foo
{
public:
	Foo(int i) : mInt(i)
	{
		std::cout << "Foo construct" << std::endl;
	}

	Foo(const Foo &copy) : mInt(copy.mInt)
	{
		std::cout << "Foo copy" << std::endl;
	}

	Foo &operator=(const Foo &copy) = default;

public:
	void Print()
	{
		std::cout << mInt << std::endl;
	}

private:
	int mInt;
};

int _tmain(int argc, _TCHAR* argv[])
{
	std::vector<Foo> fooList;
	fooList.push_back(Foo(1));
	return 0;
}



여기서 객체의 복사 때문에 쓸데 없는 오버헤드가 생깁니다. C++11에서는 RValue와 이동 생성자를 통해 이를 최적화 하게 됩니다. C++11의 STL 컨테이너들은 대부분 이동 생성자를 지원하기에 아래와 같이 클래스에 이동 생성자를 추가 하게 되면 복사가 아닌 이동으로 객체를 컨테이너에 삽입하기 때문에 훨씬 더 빠르고, 메모리 사용량도 줄일 수 있습니다.

class Foo
{
public:
	Foo(int i) : mInt(i)
	{
		std::cout << "Foo construct" << std::endl;
	}

	Foo(const Foo &copy) : mInt(copy.mInt)
	{
		std::cout << "Foo copy" << std::endl;
	}

	// 이동 생성자 추가
	Foo(Foo &&move) : mInt(0)
	{
		std::cout << "Foo move" << std::endl;
		*this = std::move(move);
	}

	Foo &operator=(const Foo &copy) = default;

public:
	void Print()
	{
		std::cout << mInt << std::endl;
	}

private:
	int mInt;
};



여기서 한가지 더 최적화 방법이 있습니다. 바로 emplace 함수를 사용 하는 것입니다. emplace 함수를 이용하면 바로 컨테이너 위치에 객체를 생성하기 때문에 이동이 발생하지도 않습니다.

int _tmain(int argc, _TCHAR* argv[])
{
	std::vector<Foo> fooList;
	fooList.emplace_back(1);
	return 0;
}




(이런 방법이 있지만 컨테이너에 대부분 포인터만 집어넣는 나는 쓸일이 없겠지...)


참조 : https://msdn.microsoft.com/ko-kr/library/dd293665.aspx

참조 : http://stackoverflow.com/questions/4303513/push-back-vs-emplace-back

참조 : http://en.cppreference.com/w/cpp/container/vector/emplace_back

+ Recent posts