Nujufas
Nujufas

Reputation: 802

Can I pass a unique_ptr's reference to a function?

Can I pass a unique_ptr's reference to a function? If not why should I avoid it?

Ex:

void func(unique_ptr<Clss>& ref);

main() {
   unique_ptr<Clss> a = std::make_unique<Clss>();
   fn(a);
}

Upvotes: 7

Views: 18450

Answers (5)

Nujufas
Nujufas

Reputation: 802

According to Herb Sutter:

https://herbsutter.com/2013/06/05/gotw-91-solution-smart-pointer-parameters/

Passing unique_ptr by reference is for in/out unique_ptr parameters.

void f( unique_ptr<widget>& ); // (d)

This should only be used to accept an in/out unique_ptr, when the function is supposed to actually accept an existing unique_ptr and potentially modify it to refer to a different object. It is a bad way to just accept a widget, because it is restricted to a particular lifetime strategy in the caller.

Thanks @sgvd

Upvotes: 6

YSC
YSC

Reputation: 40150

Passing a std::unique_ptr to a function is perfectly fine as long as you respect the same rules you would when passing a regular reference to a function:

  • the underlying std::unique_ptr and the object it points to must live at least as long as the function will use the reference;
  • in case of multi-threading, barriers must be put in place.

Upvotes: 0

ObliteratedJillo
ObliteratedJillo

Reputation: 5166

See this code snippet, two ways of passing unique_ptr as function parameter. fun1 will take ownership of the object ( hence should be forwarded from the caller) but func2 commits thats the reference unique_ptr object will be passed as reference and will not be modified by the function.

void func1(unique_ptr<Clss>&& moved_obj) // this function takes ownership
{
    //do something with the moved_obj

    moved_obj.reset();
}

void func2(const unique_ptr<Clss>& ref_obj) // this function takes reference
{
   unique_ptr<Clss> new_obj = std::make_unique<Clss>(*(ref_obj));
}


int main() {

   unique_ptr<Clss> a = std::make_unique<Clss>();
   func1(std::move(a));

   unique_ptr<Clss> b = std::make_unique<Clss>();
   func2(b);

    return 0;
}

Upvotes: 3

Jarod42
Jarod42

Reputation: 218238

I see those valid meaningful signatures:

void take_ownership(std::unique_ptr<Clss>);
// or void take_ownership(std::unique_ptr<Clss>&&);

void use(/*const*/ Clss*);
// or void use(/*const*/ Clss&);

std::unique_ptr<Clss> create(/*args..*/);

void might_take_ownership(std::unique_ptr<Clss>&);

The later might make sense, but it is more difficult to reason with (as any I/O argument).

If you can, prefer one of the other.

Upvotes: 2

Vittorio Romeo
Vittorio Romeo

Reputation: 93364

Can I pass a unique_ptr's reference to a function?

Yes, a unique_ptr is class like any other.

You should do this when you want to mutate an existing unique_ptr from a function (e.g. calling .reset() on it).

If only you want to access the object inside unique_ptr<T>, take T& or const T& in your function interfaces, so that they can be used independently of unique_ptr.

Upvotes: 8

Related Questions