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