Passing unique_ptr to functions

I am trying to "upgrade" existing code.

  • I have a class that currently has the member variable "Device * device_".
  • It uses the new to instantiate in some initialization code and has a “delete device_” in the destructor.
  • The member functions of this class call many other functions that take Device * as a parameter.

This works well, but in order to “upgrade” my code, I thought I should change the variable, which will be defined as "std::unique_ptr<Device> device_" , and delete the explicit call to delete, which makes the code more secure and generally better .

My question is

  • How do I pass the device_ variable to all functions that need it as a parameter?

I can call .get to get a raw pointer in every function call. But this seems ugly and perverts some of the reasons for using unique_ptr in the first place.

Or I can change each function so that instead of accepting a parameter of type "Device *", now it accepts a parameter of type "std :: unique_ptr &". Which (to me) confuses function prototypes a little and complicates their reading.

Which is better for this? Did I miss other options?

+44
c ++ smart-pointers unique-ptr
Mar 14 2018-12-12T00:
source share
5 answers

In modern C ++ style, there are two key concepts:

  • of property
  • Invalid

The property concerns the owner of an object / resource (in this case, a Device instance). Various std::unique_ptr , boost::scoped_ptr or std::shared_ptr belong to the property.

Nullity is much simpler: it simply expresses whether a given object can be null, and does not care about anything else, and, of course, not about ownership!




You were entitled to move the implementation of your class towards unique_ptr (in general), although you might need a smart pointer with deep copy semantics if your goal is to implement PIMPL.

This clearly indicates that your class is responsible for this chunk of memory and is neatly dealing with all the different ways that a memory leak might otherwise.




Most users of resources, on the other hand, did not care, however.

As long as the function does not save the link to the object (it stores it on the map or something else), then all that matters is that the lifetime of the object exceeds the duration of the function call.

Thus, the choice of the parameter transfer method depends on its possible Nullity:

  • Never null? Pass the link
  • Perhaps null? Pass a pointer, a simple empty pointer, or a pointer class (e.g. with a trap at level zero)



+44
Mar 14 2018-12-12T00:
source share

It really depends. If the function must belong to unique_ptr, then it must have the value unique_ptr<Device> bv , and the caller must have a std::move pointer. If ownership is not a problem, I would save the signature of the raw pointer and pass the unique_ptr pointer with get() . This is not ugly if the function in question does not acquire ownership.

+14
Mar 14 '12 at 9:50
source share

I would use std::unique_ptr const& . Using a non const reference will give the called function the ability to reset your pointer.
I think this is a good way to express that your called function can use a pointer, but nothing else.
Therefore, for me it will simplify the reading of the interface. I know that I don’t have to bother with the pointer passed to me.

+7
Mar 14 2018-12-12T00:
source share

Best practice is probably not to use std::unique_ptr in this case, although it depends. (Normally, you should not have more than one raw pointer to a dynamically allocated object in the class. Although this also depends.) The only thing you do not want to do in this case is: walking around std::unique_ptr (and, as you noticed, std::unique_ptr<> const& is a bit cumbersome and confusing). If this is the only dynamically allocated pointer in the object, I would just stick with the raw pointer and delete in the destructor. If there are several such pointers, I would think about assigning each of them to a separate base class (where they can still be raw pointers).

+2
Mar 14 2018-12-12T00:
source share

This may not be feasible for you, but replacing any appearance of Device* with const unique_ptr<Device>& is a good start.

Obviously, you cannot copy unique_ptr , and you do not want to move it. Replacing the reference with unique_ptr allows the body of the bodies of existing functions to continue to work.

Now that you have a trap, you must go past const & to prevent unique_ptr.reset() or unique_ptr().release() called. Note that this still passes a mutable pointer to the device. With this solution, you have no easy way to pass a pointer or a link to const Device .

+1
Mar 14 2018-12-12T00:
source share



All Articles