LearningCpp
LearningCpp

Reputation: 972

How does a C++ compiler decide when to call a move constructor for std::vector or any object

I was reading std template library book and was confused with below details listed in STL Containers chapter. Apparently, it specifies the STD::VECTOR Operations and the effect

Operation                     Effect

vector<Elem> c(c2)  | Copy constructor; creates a new vector as a copy of c2 (all elements are copied)
vector<Elem> c = c2 | Copy constructor; creates a new vector as a copy of c2 (all elements are copied)
vector<Elem> c(rv)  | Move constructor; creates a new vector, taking the contents of the rvalue rv (since C++11)
vector<Elem> c = rv | Move constructor; creates a new vector, taking the contents of the rvalue rv (since C++11)

Apparently, there is no difference in the syntax for both move and copy constructors, when exactly are they called?

Upvotes: 6

Views: 2087

Answers (5)

eerorika
eerorika

Reputation: 238401

Apparently , there is no difference in the syntax for both move and copy constructors

Indeed, this is true. This is not specific to std::vector either, but holds in general for all types. Copy-initialization by copy and by move have exactly the same syntax. Same goes for copy-assignment.

The difference comes from the type of argument expression. When the argument is a non-const r-value, the move constructor/assignment is preferred by overload resolution. Otherwise, move-constructor is not applicable, so copy constructor is used.

i assume rv is just a constructed object like c2

rv and c2 appear to not be objects. They are apparently placeholders for expressions. The book could be clearer about that (maybe it is, the excerpt is out of context after all).

Upvotes: 3

Rakete1111
Rakete1111

Reputation: 48998

The move constructor is called where it makes sense to call it, i.e. moving an object and using it thereafter does not make sense, as the original object has been modified (possibly), which is not desirable:

std::vector<int> a = { 1 };
std::vector<int> b = a; //Let's say this called move constructor
int value = a[0]; //value is possibly not 1, the value may have changed due to the move

So, in that case, the copy constructor is called:

std::vector<int> a = { 1, 2 };
std::vector<int> b = a; //Copy constructor

But, here it does call the move constructor, because it is assigned to an rvalue, or a temporary value:

void foo(std::vector<int>) {}
foo({ 1, 2 }); //move constructor

The vector { 1, 2 } is a temporary vector, who cares if it has been modified? You will never know, as the vector will get destructed as soon as foo has ended. Copying the temporary vector would just be a waste of time.

Upvotes: 6

Leandro T. C. Melo
Leandro T. C. Melo

Reputation: 4032

Perhaps you should decouple syntax from semantics for better understanding. Let me make an analogy, consider this code.

struct A {
  A(int i) {}
  A(const std::string& s) {}
};

Now, if you find the following line, which constructor will be called?

A a(x);

You can't tell it because you don't know whether x has type int or std::string. It's not much different in your example, but with move semantics the compiler will inspect whether the argument is an rvalue or not. If such an A class provides a (move) constructor overload and x is an rvalue reference, then it will be preferred.

Upvotes: 2

Some programmer dude
Some programmer dude

Reputation: 409356

Let say you have a function f that returns a vector by value:

std::vector<int> f();

The value returned by the function is an rvalue.

And then lets say you want to call this function to initialize a vector of yours:

std::vector<int> v = f();

Now the compiler knows the vector returned by f will not be used any more, it's a temporary object, therefore it doesn't make sense to copy this temporary object since it will just be destructed at once anyway. So the compiler decides to call the move-constructor instead.

Upvotes: 6

Khoa
Khoa

Reputation: 2932

syntax of copy constructor: classname (const classname&)

syntax of move constructor: classname (classname&&)

The calling looks same together but their declarations are different.

Ref:

http://en.cppreference.com/w/cpp/language/copy_constructor http://en.cppreference.com/w/cpp/language/move_constructor

Upvotes: -1

Related Questions