Home > Guides > Programming > C/C++

Toggle Open Guide Table of ContentsGuide Contents

Close Table of ContentsGuide Contents

Close Table of Contents

Using unique_ptr, Part I

Last updated Sep 12, 2008.

The turbulent history of auto_ptr eventually led to its deprecation in the C++0x Working Paper (I'm grateful to Howard Hinnant for pointing it out to me). C++0x introduces a new smart pointer class called unique_ptr which supports move semantics with at least the same efficiency of auto_ptr, but without the notorious limitations and runtime surprises that are associated with the latter. Find out more about the new unique_ptr class template and its usage here.

Why auto_ptr Had To Be Deprecated

The repeated modifications and patches of auto_ptr improved its safety to some extent but couldn't eliminate one serious flaw in its design: Calling a generic algorithm (e.g., std::sort()) that will operate on auto_ptr is risky because the generic algorithm might assume that something that looks like a copy operation -- is truly a copy operation. I'll show an example:

vector<auto_ptr<int> > vi;
//..populate vi
sort(vi.begin(), vi.end(), indirect_less());

Depending on the implementation of sort(), the above line of code might cause undefined behavior (often leading to a crash). The problem is that some implementations of sort() will pick an element out of the sequence, and store a local copy of it. Such implementations are perfectly valid and standard compliant. However, look what happens when they encounter vi:

value_type pivot = *mid_point; //seemingly a copy operation, but no quite so!

The sort() algorithm assumes that pivot and *mid_point are equivalent. However when value_type is an auto_ptr, this assumption fails because what appears to be a copy operation is in fact a move operation. Consequently, the algorithm fails. To fix this bug, auto_ptr was patched several years ago, disallowing standard containers to copy from const auto_ptr. This fix provides only a partial solution though. Users can still store auto_ptr objects in a built-in array. When you apply sort() to such an array, the results can be undefined behavior -- or perfectly valid, depending on the underlying implementation of sort().

Generally speaking, it's a bad idea to move from lvalues using copy syntax. Other syntax for moving should be used instead or else generic code is likely to initiate a move when a copy was intended, thus causing undefined behavior. Because auto_ptr moves from lvalues using copy syntax, it's fundamentally unsafe.

Deprecating auto_ptr

After years of debates, the C++ standards committee decided that auto_ptr should be deprecated. Since the deprecation alone will not make the problems of auto_ptr disappear it was decided that a new smart pointer class with more or less the same strict ownership semantics of auto_ptr -- but with a cleaner and safer interface -- should be added to C++0x. That replacement class is called unique_ptr. If you have used auto_ptr before, you will find unique_ptr's usage pretty straightforward. However, unlike auto_ptr, unique_ptr requires an explicit move operation for moving from lvalues; you can't use copy syntax for that purpose. Consequently, STL containers and algorithms, and in fact, any generic code will either fail to compile when operating on unique_ptr (instead of leaving the bug unreported and crashing at runtime), or it will produce valid results if unique_ptr is allowed. In addition to solving the safety problems of auto_ptr, the designers of unique_ptr decided to extend its functionality without adding space or runtime overhead (unless such overhead is explicitly requested) while still maintaining source compatibility with auto_ptr (except the ability to move from an lvalue with copy syntax).

Anything auto_ptr Can Do, But Better

It should be noted that unique_ptr is not a 100% source-compatible drop-in replacement for auto_ptr. If it were, the standards committee could simply patch auto_ptr instead of deprecating it and introducing a new class template as a replacement. That said everything you can do with auto_ptr, unique_ptr will do as well with the same syntax except for moving from lvalues:

#include <utility> 
using std::auto_ptr;
using std::unique_ptr;
// default construction
auto_ptr<int> ap;
unique_ptr<int> up;
// initialize with pointer
auto_ptr<int> ap(new int(9));
unique_ptr<int> up(new int(9));
// dereference
*ap = 23;
*up = 23;
// reset
ap.reset();
up.reset();
assert (sizeof(auto_ptr<T>) == sizeof(unique_ptr<T>));

When it comes to copy operations, there's a difference:

auto_ptr<int> ap1(new int);
auto_ptr<int> ap2 = ap1; // OK, albeit unsafe 
unique_ptr<int> up1(new int);
unique_ptr<int> up2 = up1; // compilation error: private copy ctor inaccessible

If you really want to transfer ownership from the lvalue unique_ptr, you have to use an explicit std::move() call:

unique_ptr<int> up1(new int);
unique_ptr<int> up2 = move(up1); // ok, explicit move

unique_ptr permits move from rvalues with copy syntax using a move constructor (which binds to rvalues), while blocking the copy from lvalues by making the copy constructor (which binds to lvalues) private:

template <class T>
class unique_ptr
{
public:
 unique_ptr(unique_ptr&& u);   // rvalues bind here
private:
 unique_ptr(const unique_ptr&); // lvalues bind here
};

In the next part of this series I will discuss passing unique_ptr to a function and returning unique_ptr from a function, using unique_ptr with algorithms and containers, customizing a deleter, and using unique_ptr for storing arrays.

Discussions

Bugzilla
Posted Nov 18, 2008 01:53 AM by cupu
2 Replies
auto_ptr issues
Posted Sep 14, 2007 07:43 AM by singh_siddhu
1 Replies
i want c++ book through net
Posted Aug 23, 2007 11:13 PM by harivilu
3 Replies

Make a New Comment

You must log in in order to post a comment.

Related Resources

Danny KalevBjarne Stroustrups's Stevens Talk
By Danny KalevDecember 7, 2009 No Comments

On 2nd December Bjarne Stroustrup delivered a talk about the standardization process of C++0x at the Stevens institute. Here some of the key points from his talk.

Danny KalevMinutes from the October 2009 Meeting
By Danny KalevNovember 19, 2009 No Comments

The minutes from the Santa Cruz (October 2009) meeting are available here. Even if you're not a language layer at heart, I encourage you to read them.

Danny KalevA Reader's Opinion on Attributes
By Danny KalevOctober 20, 2009 No Comments

In August I dedicated a series to the debate about C++0x attributes. I believe that it covered the subject in a balanced and detailed way, but I keep getting complaints from C++ users who don't like attributes for various reasons. Here's a recent email I received from a Polish C++ programmer. While it  doesn't represent my opinion about attributes -- I'm rather neutral about this feature and consider it a "solution waiting for a problem" -- but it suggests that attributes are still a highly controversial issue that will haunt C++ for a long time. The email is quoted here with minor edits that and as usual, with all private details removed.

See More Blogs

Informit Network