Why is auto_ptr being deprecated?
Asked Answered
A

5

108

I heard auto_ptr is being deprecated in C++11. What is the reason for this?

Also I would like to know the difference between auto_ptr and shared_ptr.

Adon answered 13/9, 2010 at 3:23 Comment(1)
Possible duplicate of Is auto_ptr deprecated?Compromise
A
100

The direct replacement for auto_ptr (or the closest thing to one anyway) is unique_ptr. As far as the "problem" goes, it's pretty simple: auto_ptr transfers ownership when it's assigned. unique_ptr also transfers ownership, but thanks to codification of move semantics and the magic of rvalue references, it can do so considerably more naturally. It also "fits" with the rest of the standard library considerably better (though, in fairness, some of that is thanks to the rest of the library changing to accommodate move semantics instead of always requiring copying).

The change in name is also (IMO) a welcome one -- auto_ptr doesn't really tell you much about what it attempts to automate, whereas unique_ptr is a fairly reasonable (if terse) description of what's provided.

Autoharp answered 13/9, 2010 at 3:45 Comment(4)
Just a note on the auto_ptr name: auto suggests automatic as in automatic variable, and it refers to one thing that auto_ptr do: destroy the managed resource in its destructor (when it goes out of scope).Mede
Further information: Here is the official rationale for deprecating auto_ptr: open-std.org/jtc1/sc22/wg21/docs/papers/2005/…Pyrotechnics
@HowardHinnant interesting doc! it is strange in a sense that if std::sort() is has a specialization for std::unique_ptr to use the move semantic as needed. I wonder why std::sort() can't be specialized for std::auto_ptr to correct the copy issue mentioned in the doc. Thanks in advance.Kedge
@Hei: std::sort doesn't have a specialization for unique_ptr. Instead it was re-specified to never copy. So auto_ptr actually does work with the modern sort. But the C++98/03 sort is just an example algorithm here: Any generic algorithm (std-supplied or user-written) that assumes that copy syntax has copy semantics will likely have a run-time error if used with auto_ptr, because auto_ptr silently moves with copy syntax. The issue is much larger than just sort.Pyrotechnics
L
37

I found the existing answers great, but from the PoV of the pointers. IMO, an ideal answer should have the user/programmer's perspective answer.

First thing first (as pointed by Jerry Coffin in his answer)

  • auto_ptr could be replaced by shared_ptr or unique_ptr depending upon situation

shared_ptr : If you are concerned about freeing of resource/memory AND if you have more than one function that could be using the object AT-DIFFERENT times, then go with shared_ptr.

By DIFFERENT-Times, think of a situation where the object-ptr is stored in multiple data-structure and later accessed. Multiple threads, of course is another example.

unique_ptr : If all you are concerned is freeing memory, and the access to object is SEQUENTIAL, then go for unique_ptr.

By SEQUENTIAL, I mean, at any point object will be accessed from one context. E.g. a object that was created, and used immediately after creation by the creator. After creation the object is stored in FIRST data-structure. Then either the object is destroyed after the ONE data-structure or is moved to SECOND data-structure.

From this line, I will refer shared/unique _ptr as smart-pointers. (auto_ptr is also smart-pointer BUT because of flaws in it's design,for which they are being deprecated, and which I think I will point out in next lines, they should not be grouped with smart-pointer. )

Single most important reason as to why auto_ptr was deprecated in favor of smart-pointer is assignment-semantics If it wasn't for that reason, they would have added all the new goodies of move semantics to the auto_ptr instead of deprecating it. Since the assignment-semantics was most-disliked feature, they wanted that feature to go away, but since there is code written that uses that semantics, (which standards-committee can not change), they had to let go of auto_ptr, instead of modifying it.

From the link : http://www.cplusplus.com/reference/memory/unique_ptr/operator=/

Kind of assignments supported by unqiue_ptr

  • move assignment (1)
  • assign null pointer (2)
  • type-cast assignment (3)
  • copy assignment (deleted!) (4)

From : http://www.cplusplus.com/reference/memory/auto_ptr/operator=/

Kind of assignments supported by auto_ptr

  • copy assignment (4) culprit

Now coming to the reason WHY the copy assignment itself was so disliked, I have this theory :

  1. Not all programmers read books or standards
  2. auto_ptr on the face of it, promises you ownership of the object
  3. the little-* (pun intended), clause of the auto_ptr, which is not read by all the programmers, allows, assignment of one auto_ptr to another, and transfers the ownership.
  4. Research has shown this behavior is intended for 3.1415926535 % of all usage, and unintended in other cases.

The unintended behavior is really disliked and hence the dislike for the auto_ptr.

(For the 3.1415926536% of programmers who intentionally wants to transfer the ownership C++11 gave them std::move(), which made their intention crystal clear for all the interns who are going to read and maintain the code.)

Levigate answered 24/2, 2013 at 6:12 Comment(8)
Since you never want two auto_ptr values pointing to the same object (since they don't give shared ownership, the first one to die will leave the other with a lethal heritage; this is also true for unique_ptr usage) , can you suggest what was intended in those remaining 96.8584073465% of all usage?Malevolent
Can't speak for the all of them, but I would guess, they would think the object ownership is being moved and NOT just duplicated, which is erroneous.Levigate
@AjeetGanga In the following phrase 'the little-* (pun intended),' you mentioned as "pun intended". This phrase is new for me and anyhow I googled it and got to know that there is some joke that was purposefully done here. What is that joke here? Just curious to know that.Braque
@AjeetGanga You mentioned like 'the little-* (pun intended), clause of the auto_ptr, which is not read by all the programmers, allows, assignment of one auto_ptr to another, and transfers the ownership'. Let say I have two auto ptr's as a and b to integer. I am doing the assignment as *a=*b; Here only value of b is copied to a. I Hope Ownership of both a and b is still with the same people. You mentioned like owenership will be transferred. How it will be?Braque
@VINOTHENERGETIC Ajeet was talking about assigning to an auto_ptr object itself. Assigning to/from its pointed-to value has no effect upon, nor relevance to, ownership. I hope you are not still using auto_ptr?Camembert
@Camembert Got it. No am not using the shared pointer now. Just a curiosity to understand the conceptBraque
it is not so much about unintended moves when "copying" an autopointer due to not reading the docs. The problem is rather that generic code runs into problems when something that looks like a copy is in fact a move. Library implementers do read books and the standard, but still there was no reasonable way to deal with auto_ptr once it is inside a containerBihari
What if you are not concerned about ownership, and only care about ensuring cleanup and code that compiles cleanly in C++03 and C++11 (and onwards).Conversationalist
P
24

shared_ptr can be stored inside containers. auto_ptr can't.

BTW unique_ptr is really the direct auto_ptr replacement, it combines the best features of both std::auto_ptr and boost::scoped_ptr.

Protraction answered 13/9, 2010 at 3:27 Comment(0)
A
13

Yet another take on explaining the difference....

Functionally, C++11's std::unique_ptr is the "fixed" std::auto_ptr: both of them are suitable when - at any point in time during execution - there should be a single smart-pointer owner for a pointed-to object.

The crucial difference is in copy-construction or assignment from another un-expiring smart pointer, shown on the => lines below:

   std::auto_ptr<T> ap(new T{...});       // OK - alloc/construct, up owns
   ...or...
   std::auto_ptr<T> ap(get_ap_to_T());   // OK - take expiring ownership

   ...then...
=> std::auto_ptr<T> ap2(ap);  // take un-expiring ownership ala ap3(ap.release());
   ap->xyz;  // oops... tried to use ap, expecting it to be non-NULL

   // --------------------------------------------------------------

   std::unique_ptr<T> up(new T{...});       // OK - alloc/construct, up owns
   ...or...
   std::unique_ptr<T> up = std::make_unique<T>(...);       // OK too
   ...or...
   std::unique_ptr<T> up(get_up_to_T());   // OK - take expiring ownership

   ...then...
=> std::unique_ptr<T> up2(up);  // COMPILE ERROR: can't take un-expiring ownership
=> std::unique_ptr<T> up2(std::move(up));  // EXPLICIT code allowed
=> std::unique_ptr<T> up2(up.release());   // EXPLICIT code allowed

Above, the ap3 auto_ptr quietly "steals" ownership of *ap, leaving ap set to a nullptr, and the problem is that can happen too easily, without the programmer having thought through its safety.

For example, if a class/struct has a std::auto_ptr member, then making a copy of an instance will release the pointer from the instance being copied: that's weird and dangerously confusing semantics as usually copying something doesn't modify it. It's easy for the class/struct author to overlook the release of the pointer when reasoning about invariants and state, and consequently accidentally attempt to dereference smart-pointer while null, or just not still have expected access/ownership of the pointed-to data.

Akmolinsk answered 12/2, 2015 at 4:21 Comment(1)
auto_ptr quietly "steals" ownership +1Prindle
C
5

auto_ptr cannot be used in STL containers because it has a copy constructor that does not meet requirements of container CopyConstructible. unique_ptr does not implement a copy constructor, so containers use alternate methods. unique_ptr can be used in containers and is faster for std algorithms than shared_ptr.

#include <iostream>
#include <type_traits>
#include <vector>
#include <memory>

using namespace std;

int main() {
  cout << boolalpha;
  cout << "is_copy_constructible:" << endl;
  cout << "auto_ptr: " << is_copy_constructible< auto_ptr<int> >::value << endl;
  cout << "unique_ptr: " << is_copy_constructible< unique_ptr<int> >::value << endl;
  cout << "shared_ptr: " << is_copy_constructible< shared_ptr<int> >::value << endl;

  vector<int> i_v;
  i_v.push_back(1);
  cout << "i_v=" << i_v[0] << endl;
  vector<int> i_v2=i_v;
  cout << "i_v2=" << i_v2[0] << endl;

  vector< unique_ptr<int> > u_v;
  u_v.push_back(unique_ptr<int>(new int(2)));
  cout << "u_v=" << *u_v[0] << endl;
  //vector< unique_ptr<int> > u_v2=u_v;  //will not compile, need is_copy_constructible == true
  vector< unique_ptr<int> > u_v2 =std::move(u_v);  // but can be moved
  cout << "u_v2=" << *u_v2[0] << " length u_v: " <<u_v.size() << endl;

  vector< shared_ptr<int> > s_v;
  shared_ptr<int> s(new int(3));
  s_v.push_back(s);
  cout << "s_v=" << *s_v[0] << endl;
  vector< shared_ptr<int> > s_v2=s_v;
  cout << "s_v2=" << *s_v2[0] << endl;

  vector< auto_ptr<int> > a_v;  //USAGE ERROR

  return 0;
}

>cxx test1.cpp -o test1
test1.cpp: In function âint main()â:
test1.cpp:33:11: warning: âauto_ptrâ is deprecated (declared at /apps/hermes/sw/gcc/gcc-4.8.5/include/c++/4.8.5/backward/auto_ptr.h:87) [-Wdeprecated-declarations]
   vector< auto_ptr<int> > a_v;  //USAGE ERROR
           ^
>./test1
is_copy_constructible:
auto_ptr: false
unique_ptr: false
shared_ptr: true
i_v=1
i_v2=1
u_v=2
s_v=3
s_v2=3
Caltrop answered 11/7, 2016 at 19:2 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.