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
.
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
.
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.
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 auto_ptr
: open-std.org/jtc1/sc22/wg21/docs/papers/2005/… –
Pyrotechnics 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 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)
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
From : http://www.cplusplus.com/reference/memory/auto_ptr/operator=/
Kind of assignments supported by auto_ptr
Now coming to the reason WHY the copy assignment itself was so disliked, I have this theory :
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.)
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 *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 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 auto_ptr
once it is inside a container –
Bihari 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
.
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.
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
© 2022 - 2024 — McMap. All rights reserved.