1

I have referred to lot of StackOverflow links on these questions where the reason for auto_ptr not working well with STL is std::auto_ptr<> does not fulfill the requirements of being copy-constructible and assignable (since auto_ptr has a fake copy constructor which basically transfers the ownership).

But even unique_ptr doesn't have copy ctor and assignment operator (it's disabled), so how is the requirement of being copy-constructible and assignable fulfilled?

curiousguy
  • 8,038
  • 2
  • 40
  • 58
anurag86
  • 1,635
  • 1
  • 16
  • 31
  • Do you have a particular example of something that requires copying but works with `unique_ptr`? – chris Nov 09 '19 at 03:53

3 Answers3

8

You're looking at the whole thing backwards.

In C++98/03, we got auto_ptr. This type lies to everyone by pretending that it supports copy semantics when in fact copying it does something very much unlike a copy operation. Therefore, any type which relies on a type providing copy semantics, like certain containers, would not take well to getting an auto_ptr. Of course, you will only find out when your code becomes dysfunctional, not at compile time.

In C++11, we got unique_ptr, a type which explicitly does not provide copy semantics. Instead, it provides move semantics, and provides them correctly. Therefore, any type which relies on a type providing copy semantics will fail to compile when given a unique_ptr.

However, the reason unique_ptr came into being at all because the concept of moving an object was added to the language in C++11. When new concepts get added to the language, existing tools, like standard library requirements, are often re-evaluated relative to that language feature.

For example, types that formerly required copy semantics did not necessarily have to keep that requirement. C++98/03 containers that required copy semantics were updated in C++11 to only require (noexcept) move semantics from a type.

So it's not that unique_ptr fulfills some requirement that auto_ptr did not. It's that the language changed to no longer need that requirement, but auto_ptr was still lying about what it did, so for backwards compatibility sake, we created a new type that respected the new language features and didn't lie to people.

Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982
  • 1
    Your answer is worth 20 other detailed posts on stackoverflow. Thsi is what i was looking for - about the change in standard which changed the requirement and ptr usage. – anurag86 Nov 09 '19 at 04:35
1

I assume you're referring to using smart pointers with STL containers.

auto_ptr can, but shouldn't be used because its copy constructor may accidentally move data (it was designed before move semantics with rvalue references were added in C++11).

unique_ptr doesn't have a copy constructor, so it can't be trivially used in STL containers. Operations that copy the pointer won't work, but that's what makes it safe. You can still explicitly use move iterators or emplace to get noncopyable elements into containers.

Examples for using unique_ptr in containers here: So can unique_ptr be used safely in stl collections?

parktomatomi
  • 3,851
  • 1
  • 14
  • 18
  • Yep. Got it. By trivially do you mean “always”? – anurag86 Nov 09 '19 at 04:42
  • Nope. Just some of the things you casually do with `vector` won't work with `unique_ptr`. If you `push_back` a `unique_ptr`, you'll get a nasty error. But if you `emplace_back` one, you might not. See the link for examples. – parktomatomi Nov 09 '19 at 04:54
  • 1
    @parktomatomi push_back works just fine with unique_ptr as long as the argument is an rvalue. – eerorika Nov 09 '19 at 05:21
1

auto_ptr looks like copy constructible / assignable, because it has a copy constructor and assignment operator.

The problem is that its copy constructor and assignment don't implement copy semantics, but move semantics instead. This makes the interface of auto_ptr surprising, and makes it unusable in containers that assign elements internally (such as vector).

What makes this worse is that using auto_ptr in a vector is well-formed (no compilation error), but doesn't have useful behaviour, which can easily lead to undefined behaviour (i.e. serious bugs).

But even unique_ptr doesn't have copy ctor and assignment operator(its disabled)

unique_ptr doesn't need to be copy constructible or assignable. It is sufficient to be move constructible and assignable for most use cases.

unique_ptr can replace all uses of auto_ptr, and doesn't have the problems of auto_ptr. Since C++11 where unique_ptr as well as language support for moving was introduced, auto_ptr has been deprecated and since C++17, auto_ptr has been removed from the standard library.

eerorika
  • 232,697
  • 12
  • 197
  • 326
  • my confusion is more towards "requirements of being copy-constructible and assignable of STL" is not still being fulfilled by unique_ptr. And the example you gave about _"makes the interface of auto_ptr surprising, and makes it unusable in containers that assign elements internally (such as vector)."_ eventually the end result is the same in case of unique_ptr too - i.e. data is moved and not copied. auto_ptr moves it through copy, unqiue_ptr does it through move. So then in such cases, what has changes that we prefer unique_ptr – anurag86 Nov 09 '19 at 04:31
  • 1
    @anurag86 Copying of unique_ptr is not surprising at all. It is fully expected that it cannot be copied. The compiler will tell it to you relatively clearly, if you think otherwise. – eerorika Nov 09 '19 at 04:35
  • 1
    @anurag86 Nothing changed in auto_ptr. It was always a flawed design. There simply wasn't a better alternative when C++ was standardised. It was usually recommended to be avoided even before its deprecation. What changed was the C++ language and the introduction of move semantics and in particular, the introduction of the unique_ptr type into the language. Unique_ptr is all that auto_ptr was supposed to be, but couldn't be because there wasn't move semantics in the language. – eerorika Nov 09 '19 at 04:44