An unique_ptr
cannot be pushed back into a std::vector
since it is non-copyable, unless std::move
is used. However, let F
be a function that returns a unique_ptr
, then the operation std::vector::push_back(F())
is allowed. There is an example below:
#include <iostream>
#include <vector>
#include <memory>
class A {
public:
int f() { return _f + 10; }
private:
int _f = 20;
};
std::unique_ptr<A> create() { return std::unique_ptr<A>(new A); }
int main() {
std::unique_ptr<A> p1(new A());
std::vector< std::unique_ptr<A> > v;
v.push_back(p1); // (1) This fails, should use std::move
v.push_back(create()); // (2) This doesn't fail, should use std::move?
return 0;
}
(2)
is allowed, but (1)
is not. Is this because the returned value is moved somehow implicitly?
In (2)
, is it actually necessary to use std::move
?
std::move(X)
essentially means "here, treat X as if it was a temporary object".
create()
returns a temporary std::unique_ptr<A>
to begin with, so move
is unnecessary.
If you want to know more, look into the value categories. Your compiler uses value categories to determine if an expression refers to a temporary object ("rvalue") or not ("lvalue").
p1
is an lvalue, and create()
is an rvalue.
std::vector::push_back()
has an overload that takes an rvalue reference as input:
void push_back( T&& value );
The return value of create()
is an unnamed temporary, ie an rvalue, so it can be passed as-is to push_back()
without needing to use std::move()
on it.
std::move()
is needed only when passing a named variable, ie an lvalue, where an rvalue is expected.
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