Jonathan Boccara's blog

Changing deleters during the life of a unique_ptr (4/7)

Published September 5, 2017 - 2 Comments

Daily C++

previous episode in the Smart developers use Smart pointers series showed how (and why) to use custom deleters in std::unique_ptr. Now let’s see the methods that change the custom deleter during the life of the unique_ptr and, also, those that don’t. This aspect of smart pointers has been pointed out to me by Mathieu Ropert and Raoul Borges. Thanks guys.

The series Smart developers use Smart pointers currently contains:

Throughout the following cases, we will use a unique_ptr on a type that can be destroyed in two different ways. To see why this can be useful, check out the post dedicated to Custom deleters.

As a toy example we use an unique_ptr on int, with a customizable deleter:

One deleter is to be used for even numbers, and another one for odd numbers:

Assigning from another std::unique_ptr

Consider the following code:

p1, that contains an even number with the appropriate deleter, is taking over the ownership of the resource in p2. The question is: how will it destroy this resource? Will it use the deleter it was built with, or rather bring over the deleter of p2 along with the ownershp of its resource?

Take a moment to think about it, then click below to uncover what this program outputs (the deleters are printing out the info – look at their code at the top of the article):

Each resource is deleted with the correct deleter, which means that the assignment did bring over the deleter. This makes sense because the resources would not be disposed of with the correct deleter otherwise.

Resetting the pointer

Another way to change the resource contained in an std::unique_ptr is to call its reset method, like in the following simple example:

The reset method calls the deleter on the current resource (42), and then takes on the new one (43).

But the reset mehods only takes one argument, which is the new resource. It cannot be passed a deleter along with this new resource. For that reason, it can no longer be used directly in our example with even and odd numbers. Indeed, the following code:

naturally outputs:

which is incorrect in our case.

In fact we could manually change the deleter in a separate statement, by exploiting the fact that the get_deleter method of unique_ptr returns the deleter by non-const reference (thanks to Marco Arena for pointing this out):

But why doesn’t reset have a deleter argument? And how to hand over a new resource to an std::unique_ptr along with its appropriate deleter in a single statement?

Howard Hinnant, who is amongst many other things lead designer and author of the std::unique_ptr component, answers this question on Stack Overflow:

unique_ptr reset deleter

And here is how to use his answer in our initial example:

which gives the following desired output:

Thanks to Howard for providing that solution.

Stay tuned for the next episode of the series Smart Developers Use Smart Pointers!

Related articles:

Share this post! Facebooktwittergoogle_pluslinkedin    Don't want to miss out ? Follow:   twitterlinkedinrss

Receive regular updates to make your code more expressive.