c++unique-ptrauto-ptr

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


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?


Solution

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

    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.