5

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) }
    {
    }
};
keith
  • 5,122
  • 3
  • 21
  • 50
  • Does the second one even works? – 101010 Apr 05 '17 at 14:29
  • If your team gets less confused by the latter and will waste less time asking you to explain it, use the latter. – Kerrek SB Apr 05 '17 at 14:29
  • @KerrekSB did OP ask about team confused and waste of time? – Slava Apr 05 '17 at 14:30
  • @101010 of course it does! `bar b{ std::make_unique(69) };` – keith Apr 05 '17 at 14:31
  • OK but what if try to enter an already existant std::unique_ptr (e.g., `std::unique_ptr uptr {new int}; bar b(uptr);`) – 101010 Apr 05 '17 at 14:32
  • @101010 you will need to move it – Slava Apr 05 '17 at 14:33
  • 2
    @101010 Then neither would compile. Which is a good thing. – juanchopanza Apr 05 '17 at 14:33
  • 1
    @101010 `bar b{ std::move(other) };` - who's asking the question here? – keith Apr 05 '17 at 14:33
  • What I'm trying to say is that passing `std::unique_ptr` by copy is not a good thing IMHO. You give wrong signals. – 101010 Apr 05 '17 at 14:34
  • @101010 Yep, passing by copy is certainly not a good thing because it won't compile. Possible dupe of [this](https://stackoverflow.com/questions/8114276/how-do-i-pass-a-unique-ptr-argument-to-a-constructor-or-a-function?rq=1) – Praetorian Apr 05 '17 at 14:36
  • 1
    @Slava: The OP asked about "any differences". The purpose of using C++ is to get stuff done, so if there's an impact on the ability to get stuff done, I'd consider that noteworthy. – Kerrek SB Apr 05 '17 at 14:36
  • related/maybe dupes: [1](http://stackoverflow.com/questions/37935393/pass-by-value-vs-pass-by-rvalue-reference), [2](http://stackoverflow.com/questions/38140495/accept-move-only-parameter-by-value-or-rvalue-reference) – NathanOliver Apr 05 '17 at 14:38
  • @KerrekSB OP asked "any differences ... in terms of how the compiler handles them". If you consider that noteworthy you skip answering, I think this is legit question. – Slava Apr 05 '17 at 14:38

1 Answers1

6

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.

Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
  • In C++17, that extra move will be guaranteed to be elided right? – NathanOliver Apr 05 '17 at 14:46
  • 2
    @NathanOliver: no, that's nothing to do with that. That's why I *hate* the term "guaranteed copy elision", it just confuses everyone. – Kerrek SB Apr 05 '17 at 14:47
  • @NathanOliver: Basically, you should reject all blanked "X will solve all Y" claims, they're all nonsense. – Kerrek SB Apr 05 '17 at 14:48
  • What term would you give it then – Hatted Rooster Apr 05 '17 at 14:51
  • 4
    @GillBates: Maybe "Simplified value categories", something like that. "Prvalues are not objects". The latter describes the change precisely. (Since there are no objects, no objects are copied.) Now it's also immediately clear why that has nothing to do with the present question. And it doesn't advertise with the absence of something that doesn't exist in the first place. – Kerrek SB Apr 05 '17 at 14:54