To show you an example of move semantic in effect, we experiment by starting with the following class:
#includeif we run the program, we would get#include using namespace std; class Foo { public: Foo(int cnt, char * ptr) { _content = cnt; _pContent = new char [strlen(ptr)]; strcpy(_pContent, ptr); cout << "initializing the object" << endl; cout << _pContent << endl; } private: int _content; char * _pContent; }; int main() { char * str = "Hello World!"; Foo foo(10, str); }
[leorex@localhost move_semantic]$ ./a.out
initializing the object
Hello World!
Easy enough. Now let a function initialize Foo, and we will return the result to main Here I will use the example of integer pointer just to make the code shorter
#includeRunning result involves a lot of calling to copy constructor, which is hardly surprisingusing namespace std; class Foo { public: Foo(int * cnt) { _content = new int; *_content = *cnt; cout << "initializing the object" << endl; } Foo() { _content = new int; *_content = 0; cout << "Running default constructor" << endl; } Foo & operator=(const Foo & rhs) { cout << "call the copy assignment" << endl; if(_content == NULL) _content = new int; *_content = *rhs._content; } // destructor ~Foo() { cout << "destroying an object" << endl; if (_content != NULL) delete _content; } Foo (const Foo & rhs) { cout << "call the copy constructor" << endl; if(_content == NULL) _content = new int; *_content = *rhs._content; } private: int *_content; }; Foo init() { int i = 20; Foo foo(&i); return foo; } int main() { int i = 10; Foo foo = init(); Foo bar(&i); swap(foo, bar); }
[leorex@localhost move_semantic]$ ./03 initializing the object initializing the object call the copy constructor call the copy assignment call the copy assignment destroying an object destroying an object destroying an objectWith the move constructor and move assignment operator, things are different
#includeResult shows that swap only involves moving the pointers around.using namespace std; class Foo { public: Foo(int * cnt) { _content = new int; *_content = *cnt; cout << "initializing the object" << endl; } Foo() { _content = new int; *_content = 0; cout << "Running default constructor" << endl; } Foo & operator=(Foo&& rhs) { cout << "call the move assignment" << endl; _content = rhs._content; rhs._content = NULL; } // destructor ~Foo() { cout << "destroying an object" << endl; if (_content != NULL) delete _content; } // move constructor Foo (Foo && rhs) { cout << "call the move constructor" << endl; _content = rhs._content; rhs._content = NULL; } private: int *_content; }; Foo init() { int i = 20; Foo foo(&i); return foo; } int main() { int i = 10; Foo foo = init(); Foo bar(&i); swap(foo, bar); }
[leorex@localhost move_semantic]$ ./11 initializing the object initializing the object call the move constructor call the move assignment call the move assignment destroying an object destroying an object destroying an object