GotW #89: Smart Pointers

NOTE: Last year, I posted three new GotWs numbered #103-105. I decided leaving a gap in the numbers wasn’t best after all, so I am renumbering them to #89-91 to continue the sequence. Here is the updated version of what was GotW #103.

 

There’s a lot to love about standard smart pointers in general, and unique_ptr in particular.

 

Problem

JG Question

1. When should you use shared_ptr vs. unique_ptr? List as many considerations as you can.

Guru Question

2. Why should you almost always use make_shared to create an object to be owned by shared_ptrs? Explain.

3. Why should you almost always use make_unique to create an object to be initially owned by a unique_ptr? Explain.

4. What’s the deal with auto_ptr?

9 thoughts on “GotW #89: Smart Pointers

  1. I often use the unique_ptr, because it allows the responsibility of the single object (and its security), I also use it because it can destroy the object when it is pointed more accessible. and the management of life of the equipment.

  2. I’ve a question that I hope is covered in the solution. make_shared enables an optimization in that it can allocate the control block along with the actual object. Presumably this improves locality, and could even eliminate one memory allocation. But what happens if the class being instantiated has class-specific new and delete operators. Will make_shared use that one (and thus still make a separate allocation for the control block)?

  3. 1. when shared owner ship is desired the shared_ptr can be used, otherwise default to unique_ptr
    2. make_shared allows for some allocation optimisation (allocating the Control block next the the data). Also encapsulating the `new` makes it safer when creating a shared_ptrs at the call site of a function.
    3. make_unique solves the same problem as make_shared when used at all call site and thus is a good habit to get into where ever a unique_ptr is desired.

        //if either fails, then a leak could occure
        f(new int(3), new double(5.6)); 
    
        //if either fails all resources will be cleaned up
        f(make_unique(3), make_unique(5.6)); 
    

    4. auto_ptr is depricated

  4. 1: depends on whether you have a clear owner or not of a resource
    2&3: not much of compelling reasons really. saving an extra copy maybe. it might be safer, but for limited cases IMO.
    4: main drawback AFAIK it does not behave well with STL containers.

  5. I’ll give it a small try.

    1) One should use shared_ptr when the ownership of a resource is shared between several objects and the order of destruction of these objects is not known at design-time.

    2&3) The make_x() functions are preferable over manual new + creation of a smart pointer because
    – it is exception-safe if one of the constuctor arguments throws
    – it enables some allocation optimization (although not required by the standard)
    – it saves typing.

    4) auto_ptr never existed. These aren’t the droids you are looking for. *waves his hand*. :)

  6. I like make_shared and make_unique. They make my code safer and shorter.

    Usually.

    The exception is when you reset a smart pointer.

    smart.reset(new SomeType(val1, val2));

    is shorter than

    smart = std::unique_ptr<SomeType>(val1, val2);

    And I know that’s safe, so it undercuts the “Never use new” mantra a bit.

    It would be great if the library supported this:

    smart.emplace_reset(val1, val2);
  7. Regarding #4, I assume the eventual advice will include things like being able to banish “naked new” as a pedagogical point, and maintaining exception safety when there’s multiple arguments, e.g.

    void f(unique_ptr<Foo>, unique_ptr<Bar>);
    f(new Foo, new Bar);  // leaks if the first ctor called -- whichever that is -- throws
    

    But, IMHO, these result in a much less persuasive argument for *always* using make_unique compared to the situation for make_shared which is much more cut and dry, especially since make_unique was left out of C++11. Yeah, I know it’s only a few lines and it’s in C++14, but as long as you aren’t passing multiple arguments and you aren’t writing example code for a book, I’m not seeing the real burning need for make_unique.

Comments are closed.