I want to pass a std::unique_ptr
to the constructor of a class that will take ownership of the data owned by the std::unique_ptr
.
Are there any differences between the approaches foo
and bar
below in terms of how the compiler handles them that would make one of them preferable?
foo
class:
template <class T>
class foo
{
std::unique_ptr<T> data_;
public:
foo(std::unique_ptr<T>&& data) :
data_{ std::forward<std::unique_ptr<T>>(data) }
{
}
};
bar
class:
template <class T>
class bar
{
std::unique_ptr<T> data_;
public:
bar(std::unique_ptr<T> data) :
data_{ std::move(data) }
{
}
};
Binding to a reference requires one less move:
void f(std::unique_ptr<T>&& p) { g(std::move(p)); }
f(std::make_unique<T>()); // no move, g binds directly to the temporary
Binding to an object parameter requires one actual move:
void f(std::unique_ptr<T> p) { g(std::move(p)); }
f(std::make_unique<T>()); // p constructed (= moved) from temporary,
// g binds to p
The extra move involves one pointer copy, one setting of a pointer to null, and one destructor with a condition check. This is not a big cost, and the question of which style to use depends on the kind of code you're writing:
The more leaf your code is and the less it is used, the more the simple version with by-value passing buys you simplicity. Conversely, the more library your code is and the less you know your users, the more there is value in not imposing avoidable cost, no matter how small.
You decide.
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