C++: unique_ptr vs auto_ptr, and advantages of unique_ptr over auto_ptr?
Asked Answered
C

1

5

I do not fully understand the benefits of unique_ptr over auto_ptr, or I am not yet fully convinced why we need to use unique_ptr.

I see the following differences.

1) unique_ptr supports arrays and thus the unique_ptr destructor calls delete [] for arrays whereas the auto_ptr destructor calls only delete.

2) std::move() has to be used instead of directly copying in case of unique_ptr. But what advantage do we get with std::move()? I will try to explain as below.

auto_ptr <int> p1 (new int);
auto_ptr <int> p2 = p1;    // Now p1 is NULL and p2 exists with value of p1

unique_ptr <int> p1 (new int);
unique_ptr <int> p2 = std::move(p1);    // Now p1 is NULL and p2 exists with value of p1

so what is the advantage we are going to get with this?

3) I read on the Internet that unique_ptr can be used in containers. But if I understood correctly, this is not the great thing of unique_ptr. Container function semantics are changed so now a days, copying is not getting done inside of the container functions. But how is this the great thing of unique_ptr? Now that container functions are changed, why we cannot use auto_ptr in containers?

Childers answered 14/8, 2014 at 23:45 Comment(7)
The advantage of having to move is that you're moving it to move ownership instead of copying it to move ownership. The latter makes so little sense.Headboard
The main advantage is that the additions made to unique_ptr make it safe to use in STL containers. auto_ptr is not container-safe.Blader
@RemyLebeau : The same thing I mentioned in my 3rd point. We can use unique_ptr now in containers because container functions are modified (to not use copying). So we can also use auto_ptr now in containers.Childers
My understanding is that auto_ptr is still not container safe in C++11. unique_ptr was created to address all of the shortcomings of auto_ptr, and auto_ptr itself has not been changed.Blader
No, you can't use auto_ptr in containers, it's still not safe.Chalcidice
I believe it would be correct to say that C++11 containers will make use of move actions if possible but with auto_ptr its still not possible.Karolinekaroly
auto_ptr is not container safe because it does not support proper copy/move sematics that containers expect. It can steal ownership at times when stealing is not desired, thus objects might get freed prematurely. unique_ptr does not suffer from that problem. Another advantage of unique_ptr is that it supports a custom deleter, which makes it possible to have it manage resources that are not allocated with new or new[]. auto_ptr does not support that.Blader
C
11

First of all, auto_ptr has/had magic constructors, like auto_ptr(auto_ptr &other) {...}, which would behave like:

  • First copying from other instance.
  • Then null-constructing other instance.

Nowadays compilers support std::move(...), hence no need for "copy-style" constructor that did in reality "move", but to support old code, auto_ptr was left unchanged, and instead got deprecated (to be removed later).

unique_ptr forces you to be explicit about transferring ownership, so it is visible and clear in the code. With auto_ptr it is too easy to get silent transfers of ownership and when reading the code it's not always clear whether ownership is transferred, and if it is, whether it was intended by the author of the code or is a bug! When you see a unique_ptr used with std::move it is obvious that the intention is to transfer ownership.

unique_ptr properly supports move semantics, so it only allows ownership transfer from temporaries and moved objects (i.e. rvalues). Containers can detect if a type is "move aware" and act appropriately. auto_ptr does not know about move semantics, and will transfer ownership from lvalues or rvalues, so containers think it's a normal copyable object, but it doesn't behave like one because it modifies its source when copying.

auto_ptr was useful when used carefully, but it was too easy to misuse it and write dangerous code. It is time for it to die. unique_ptr supports everything auto_ptr can do, but is safe by default (you have to try harder to use it wrong) and also has extra features like custom deleters and array support.

Chalcidice answered 15/8, 2014 at 0:17 Comment(4)
Why do you think the committee didn't choose the option of enhancing auto_ptr? For example they simply added move ctor to std::ifstream instead of defining something like std::movable_ifstream.Crosscountry
@Crosscountry Adding move functions to auto_ptr doesn't help unless you remove the weird copy semantics, which will break compatibility.Bergeron
Exactly. You can make fstream movable and no existing code breaks, noone was writing code that moved fstream objects before. But if you change auto_ptr from being weird to having conventional C++11 move semantics all the existing code that (intentionally or accidentally) relied on it being weird will break.Chalcidice
Hmm, so you folks really dislike auto_ptr(auto_ptr&)... I would be happy enough if I had STL-compatible auto_ptr with custom deleterCrosscountry

© 2022 - 2024 — McMap. All rights reserved.