I am confused about using std::move()
in below code:
If I uncomment line at (2) the output would be: 1 2 3
but if I uncomment line at (1) output would be nothing which means that move constructor of std::vector
was called!
Why do we have to make another call to std::move
at (1) to make move constructor of std::vector
to be called?
What I understood that std::move
get the r-value
of its parameter so, why we have to get the r-value
of r-value
at (1)?
I think this line _v = rv;
at (2) is more logical and should make std::vector
move constructor to be called without std::move
because rv
itself is r-value
reference in the first place.
template <class T>
class A
{
public:
void set(std::vector<T> & lv)
{
}
void set(std::vector<T> && rv)
{
//_v = std::move(rv); (1)
//_v = rv; (2)
}
private:
std::vector<T> _v;
};
int main()
{
std::vector<int> vec{1,2,3};
A<int> a;
a.set(std::move(vec));
for(auto &item : vec)
cout << item << " ";
cout << endl;
return 0;
}
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.
std::move is totally unnecessary when returning from a function, and really gets into the realm of you -- the programmer -- trying to babysit things that you should leave to the compiler.
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 is used to indicate that an object t may be "moved from", i.e. allowing the efficient transfer of resources from t to another object.
Every named object is Lvalue ref about Lvalue:
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;
vector
has two overloads of assignment operator, one for Lvalue reference and another for Rvalue reference.
vector::operator=(const vector&) // copy assignment operator
vector::operator=(vector&&) // move assignment operator
Overload which takes Lvalue reference is called when Lvalue is passed as argument for operator=
.
Details here
when a function has both rvalue reference and lvalue reference overloads, the rvalue reference overload binds to rvalues (including both prvalues and xvalues), while the lvalue reference overload binds to lvalues
By std::move(rv);
you cast rv
- Lvalue to Rvalue reference, and operator=
which takes Rvalue reference is called. Otherwise, Lvalue binds to Lvalue reference and vector is copied instead of being moved.
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