Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Passing std::unique_ptr to constructor to take ownership

Tags:

c++

c++11

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) }
    {
    }
};
like image 770
keith Avatar asked Apr 05 '17 14:04

keith


1 Answers

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.

like image 131
Kerrek SB Avatar answered Oct 07 '22 18:10

Kerrek SB