195

With the new standard coming (and parts already available in some compilers), the new type std::unique_ptr is supposed to be a replacement for std::auto_ptr.

Does their usage exactly overlap (so I can do a global find/replace on my code (not that I would do this, but if I did)) or should I be aware of some differences that are not apparent from reading the documentation?

Also if it is a direct replacement, why give it a new name rather than just improve the std::auto_ptr?

Melebius
  • 4,692
  • 3
  • 32
  • 43
Martin York
  • 234,851
  • 74
  • 306
  • 532

4 Answers4

225

You cannot do a global find/replace because you can copy an auto_ptr (with known consequences), but a unique_ptr can only be moved. Anything that looks like

std::auto_ptr<int> p(new int);
std::auto_ptr<int> p2 = p; 

will have to become at least like this

std::unique_ptr<int> p(new int);
std::unique_ptr<int> p2 = std::move(p);

As for other differences, unique_ptr can handle arrays correctly (it will call delete[], while auto_ptr will attempt to call delete.

Klaim
  • 60,771
  • 31
  • 121
  • 186
Cubbi
  • 43,318
  • 13
  • 94
  • 159
  • 110
    on the other hand, doing this find/replace will only result in compile errors, it won't silently break code as far as I can see. So it is safe to do, if you manually fix the compile errors afterwards – jalf Aug 10 '10 at 16:43
  • 7
    @jalf: Indeed, I can't think of a counter-example that would be well-defined with auto_ptrs and UB with unique_ptrs. – Cubbi Aug 10 '10 at 17:25
  • 1
    so it seems like unique_ptr is an enhancement of auto_ptr: support array & remove ambiguity – baye Jul 12 '12 at 09:13
96

std::auto_ptr and std::unique_ptr are incompatible in someways and a drop in replacement in others. So, no find/replace isn't good enough. However, after a find/replace working through the compile errors should fix everything except weird corner cases. Most of the compile errors will require adding a std::move.

  • Function scope variable:
    100% compatible, as long as you don't pass it by value to another function.
  • Return type:
    not 100% compatible but 99% compatible doesn't seem wrong.
  • Function parameter by value:
    100% compatible with one caveat, unique_ptrs must be passed through a std::move call. This one is simple as the compiler will complain if you don't get it right.
  • Function parameter by reference:
    100% compatible.
  • Class member variable:
    This one is tricky. std::auto_ptrs copy semantics are evil. If the class disallows copying then std::unique_ptr is a drop in replacement. However, if you tried to give the class reasonable copy semantics, you'll need to change the std::auto_ptr handling code. This is simple as the compiler will complain if you don't get it right. If you allowed copying of a class with a std::auto_ptr member without any special code, then shame on you and good luck.

In summary, std::unique_ptr is an unbroken std::auto_ptr. It disallows at compile time behaviors that were often errors when using a std::auto_ptr. So if you used std::auto_ptr with the care it needed, switching to std::unique_ptr should be simple. If you relied on std::auto_ptr's odd behavior, then you need to refactor your code anyway.

deft_code
  • 51,579
  • 27
  • 135
  • 215
  • 9
    +1 for "you need to refactor your code anyway". auto_ptrs are only good for what 20.4.5/3 says they are good for. – Cubbi Aug 10 '10 at 17:22
  • 8
    Let me add to this that you should, by all means, replace auto_ptr by unique_ptr in your code and fix the compilation errors. You'd be surprised how many bugs this will uncover. – Bartosz Milewski Nov 30 '10 at 23:07
37

AFAIK, unique_ptr is not a direct replacement. The major flaw that it fixes is the implicit transfer of ownership.

std::auto_ptr<int> a(new int(10)), b;
b = a; //implicitly transfers ownership

std::unique_ptr<int> a(new int(10)), b;
b = std::move(a); //ownership must be transferred explicitly

On the other hand, unique_ptr will have completely new capabilities: they can be stored in containers.

UncleBens
  • 38,655
  • 6
  • 51
  • 88
  • 9
    Scott Meyers also mentioned in his "Effective C++" (3rd Edition) Item 13 (page 64) that STL containers require that their contents exhibit "normal" copying behavior, so containers of `auto_ptr` aren't allowed. – Qiang Xu Oct 29 '12 at 17:08
34

Herb Sutter has a nice explanation on GotW #89:

What’s the deal with auto_ptr? auto_ptr is most charitably characterized as a valiant attempt to create a unique_ptr before C++ had move semantics. auto_ptr is now deprecated, and should not be used in new code.

If you have auto_ptr in an existing code base, when you get a chance try doing a global search-and-replace of auto_ptr to unique_ptr; the vast majority of uses will work the same, and it might expose (as a compile-time error) or fix (silently) a bug or two you didn't know you had.

In other words, while a global search-and-replace may "break" your code temporarily, you should do it anyway: It may take some time to fix the compile errors, but will save you a lot more trouble in the long run.

ValarDohaeris
  • 5,269
  • 5
  • 25
  • 41