I was reading a book about data structure implemented in C++, I dont understand a code snippet, it's part of vector class
void push_back(object &&x) {
//do something
objects[size++] = std::move(x);
}
I know that std::move
return a rvalue reference of the object, but the push_back
member function already has rvalue reference x
as parameter, isn't the std::move
here unnecessary?
Another question is if we have a rvalue reference of a class object, we still need to use std::move
on its member if we want to call move instead of copy right? like the code below:
A& operator=(A&& other) {
member = std::move(other.member);
return *this;
}
std::move itself does "nothing" - it has zero side effects. It just signals to the compiler that the programmer doesn't care what happens to that object any more. i.e. it gives permission to other parts of the software to move from the object, but it doesn't require that it be moved.
Rvalue references is a small technical extension to the C++ language. Rvalue references allow programmers to avoid logically unnecessary copying and to provide perfect forwarding functions. They are primarily meant to aid in the design of higer performance and more robust libraries.
std::move takes an object and casts it as an rvalue reference, which indicates that resources can be "stolen" from this object. std::forward has a single use-case: to cast a templated function parameter of type forwarding reference ( T&& ) to the value category ( lvalue or rvalue ) the caller used to pass it.
In C++11, std::move is a standard library function that casts (using static_cast) its argument into an r-value reference, so that move semantics can be invoked. Thus, we can use std::move to cast an l-value into a type that will prefer being moved over being copied. std::move is defined in the utility header.
isn't the std::move here unnecessary?
No. Types and value categories are different things.
(emphasis mine)
Each C++ expression (an operator with its operands, a literal, a variable name, etc.) is characterized by two independent properties: a type and a value category.
The following expressions are lvalue expressions:
the name of a variable, a function, a template parameter object (since C++20), or a data member, regardless of type, such as std::cin or std::endl. Even if the variable's type is rvalue reference, the expression consisting of its name is an lvalue expression;
std::move
converts lvalue to rvalue (xvalue). As a named variable, x
is an lvalue, std::move
converts it to rvalue in objects[size++] = std::move(x);
then the move assignment operator is supposed to be used. Otherwise, copy assignment operator will be used instead; lvalue can't be bound to rvalue reference.
we still need to use
std::move
on its member if we want to call move instead of copy right?
Yes, same reason as above.
x
has a name, thus it's an lvalue inside the function. The rvalue reference was bound to the lvalue x
. std::move
casts it back to the rvalue that was passed in.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With