When is the call to Move Constructor called?

I am confused when the move constructor gets called against the copy constructor. I read the following sources:

The move constructor is not called in C ++ 0x

Move rvalue semantics and links in C ++ 11

msdn

All of these sources are either too complex (I just want a simple example) or just show how to write a move constructor, but not what to call it. I wrote a simple problem to be more specific:

const class noConstruct{}NoConstruct; class a { private: int *Array; public: a(); a(noConstruct); a(const a&); a& operator=(const a&); a(a&&); a& operator=(a&&); ~a(); }; a::a() { Array=new int[5]{1,2,3,4,5}; } a::a(noConstruct Parameter) { Array=nullptr; } a::a(const a& Old): Array(Old.Array) { } a& a::operator=(const a&Old) { delete[] Array; Array=new int[5]; for (int i=0;i!=5;i++) { Array[i]=Old.Array[i]; } return *this; } a::a(a&&Old) { Array=Old.Array; Old.Array=nullptr; } a& a::operator=(a&&Old) { Array=Old.Array; Old.Array=nullptr; return *this; } a::~a() { delete[] Array; } int main() { a A(NoConstruct),B(NoConstruct),C; A=C; B=C; } 

currently A, B and C have different pointer values. I would like A to have a new pointer, B to have an old pointer to C, and C to have a null pointer.

A bit off topic, but if one could offer documentation where I could learn more about these new features, I would be grateful and probably would not need to ask many more questions.

+16
c ++ c ++ 11 move-constructor
Oct 29 '12 at 16:22
source share
2 answers

The move constructor is called:

  • when the initializer of the std::move(something) object
  • when the object initializer is std::forward<T>(something) and T not a lvalue reference type (useful in programming templates for "perfect forwarding")
  • when the object initializer is temporary and the compiler does not completely exclude copy / move.
  • when returning a local object of a function by value, and the compiler does not exclude copying / moving the whole
  • when throwing an object-object of a local class and compiler, copying / moving the whole is not excluded

This is not a complete list. Note that an “object initializer” can be an argument to a function if the parameter has a class type (non-reference).

 a RetByValue() { a obj; return obj; // Might call move ctor, or no ctor. } void TakeByValue(a); int main() { a a1; a a2 = a1; // copy ctor a a3 = std::move(a1); // move ctor TakeByValue(std::move(a2)); // Might call move ctor, or no ctor. a a4 = RetByValue(); // Might call move ctor, or no ctor. a1 = RetByValue(); // Calls move assignment, a::operator=(a&&) } 
+21
Oct 29
source share

First of all, your copy constructor is broken. Both copied and copied objects will point to the same Array and will try to delete[] when they go out of scope, which will lead to undefined behavior. To fix this, make a copy of the array.

 a::a(const a& Old): Array(new int[5]) { for( size_t i = 0; i < 5; ++i ) { Array[i] = Old.Array[i]; } } 

Now the assignment move doesn't work the way you want, because both assignment operators assign lvalues ​​instead of using rvalues. For the movements that need to be performed, you must go from rvalue, or it should be a context where an lvalue can be considered an rvalue (for example, a function return statement).

To get the desired effect, use std::move to create a link to rvalue.

 A=C; // A will now contain a copy of C B=std::move(C); // Calls the move assignment operator 
+4
Oct 29 '12 at 16:35
source share



All Articles