C++11에 와서 가장 큰 변화점 중 하나가 RValue와 이동 생성자의 지원이라 할수 있을 것 같습니다. C++11 이전에는 컨테이너에 객체를 삽입 한다고 하면, 보통 객체를 복사해 컨테이너에 삽입 되는 형식이었습니다.
class Foo { public: Foo(int i) : mInt(i) { std::cout << "Foo construct" << std::endl; } Foo(const Foo ©) : mInt(copy.mInt) { std::cout << "Foo copy" << std::endl; } Foo &operator=(const Foo ©) = 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 ©) : 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 ©) = 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