Reputation: 972
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
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
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
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
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
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