Need some help understanding C++11 Move Constructors

c++, c++11, move-semantics

Solution

There are two moves that could happen in your program:

- From the function to the return object.

- From the return object to `model`.

Both of these moves can be elided by the compiler for the same reason:

when a temporary class object that has not been bound to a reference (12.2) would be copied/moved to a class object with the same cv-unqualified type, the copy/move operation can be omitted by constructing the temporary object directly into the target of the omitted copy/move

There are other situations in which copy/move elision occurs (see §12.8/31 in C++11). Note that copy/move elision is entirely optional - the compiler doesn't have to do it.

Note that the compiler is allowed to optimize absolutely anything away as long as it doesn't change the behaviour of your program (under the as-if rule). The reason that copy/move elision is explicitly mentioned in the standard is because it might change the behaviour of your program if your copy/move constructors have side effects. The compiler is allowed to perform this optimization even if it changes the behaviour of your program. This is why your copy/move constructors should never have side effects, because then your program will have multiple valid execution paths.

You can pass the `-fno-elide-constructors` option to `gcc` to ensure that this optimization is never performed.

Problem

As a C++ newbie I really have problems understanding the new Move-Constructor of C++11 and I hope someone can explain a specific situation I stumbled upon. Let's take this example code: ``` #include <iostream> using namespace std; class Model { public: int data; Model(int data) : data(data) { cout << "Constructor" << endl; } Model(Model&& model) { cout << "Move constructor" << endl; } ~Model() { cout << "Destructor" << endl; } private: Model(const Model& model); const Model& operator=(const Model&); }; Model createModel(int data) { return Model(data); } int main(void) { Model model = createModel(1); cout << model.data << endl; return 0; } ``` So I have created a `createModel` function which should return a model as a temporary rvalue and I want to assign it to an lvalue. I don't want the compiler to create copies of the `Model` object so I define the copy constructor as private and I do the same with the assignment operator to make sure no data is copied. After doing this the code correctly no longer compiles so I added the Move constructor and now it compiles again. But when I run the program I get this output: ``` Constructor 1 Destructor ``` So the Move Constructor was never called. I don't understand why I have to specify the move constructor to be able to compile the program when it is not used at all during runtime. Is it because the compiler (GCC 4.8.2) optimizes the Move Constructor away? Or is there some other magic performed here? So can someone please explain what exactly happens in the code above? The code does what I want but I really don't understand why.

Original source

Related problems