This question raised after reading this tutorial: http://www.cprogramming.com/tutorial/auto_ptr.html
There you can find the following statement: A subtle consequence of this behavior is that auto_ ptrs don't work well in all scenarios. For instance, using auto _ptr objects with the standard template library can lead to problems as some functions in the STL may make copies of the objects in containers such as the vector container class. One example is the sort function, which makes copies of some of the objects in the container being sorted. As a consequence, this copy can blithely delete the data in the container!
Most of the papers concerning 'auto_ptr' tell us something like following:
"Never use 'auto_ptr' with STL containers! They often copy their elements while performing intrinsic operations. For example consider sort
on std::vector
".
So my goal is to write the code sample that illustrates this point or prove that such examples are only theoretically true and weird on practice.
P.S. @everybody_who_also_knows_that_auto_ptr_is_deprecated
I also know this. But don't you consider technical reasons (legacy code or old compiler) that may not allow new pointer containers usage? And moreover this question is about old and bad (if you'd like) auto_ptr
.
From what you write, it seems that you already know everything that there is to know about containers of
auto_ptr
s and why they are unsafe.Therefore, I assume that your interest in containers of
auto_ptr
s is purely teaching oriented. I understand your frustration in attempting to build a deliberate counter-example: in fact, most implementers of standard containers have put in place work-arounds to avoid accidentally triggering the broken semantics ofauto_ptr
s.So, here's an example that I have written myself precisely for teaching:
Compiling it with g++ 4.9.2 will lead to an executable that will segfault nicely.
You can rewrite the example above even more concisely by using type deduction:
Note that the problem is not in the specific implementation of
std::sort
, which seems to beauto_ptr
-safe. It is rather in the comparison lambda function I am passing tostd::sort
, that deliberately accepts its arguments by value, thus destroying the objects in the container every time a comparison is performed.If you changed the lambda so that it receives its arguments by reference, as shown below, most STL implementations would actually behave correctly, even if you are doing something that is conceptually wrong.
Good luck!
IIRC, it is the other way around: the compiler vendor takes steps to prevent you from compiling something that you shouldn't be able to do. The way the standard is written, they could implement the library in a way that the code compiles, and then fails to work properly. They can also implement it this way, which is seen as superior because it's one of those few times where the compiler is actually allowed to prevent you from doing something stupid :)
The right answer is "never use auto_ptr at all" -- its deprecated and never became part of the standard at all, for precisely the reasons outlined here. Use std::unique_ptr instead.
STEP 1 Lets' solve this problem in a straight way:
On MSVCPP11 the error text is following: _Error 1 error C2558: class 'std::auto_ptr<Ty>': no copy constructor available or copy constructor is declared 'explicit' c:\program files (x86)\microsoft visual studio 11.0\vc\include\xmemory0 608
The conclusion is: I even cannot compile such example. Why do they prevent me to do something that I cannot compile?? Their preventions are not always true.
STEP 2
We cannot use
auto_ptr
asvector
element type directly due toauto_ptr
design. But we can wrap `auto_ptr' in the way presented below.This code works well showing that
auto_ptr
can be used withvector
andsort
with no memory leaks and crashes.STEP 3 As KennyTM posted below:
add this code before
return 0;
statement:...and get memory leaks!
CONCLUSION Sometimes we can use
auto_ptr
with containers without visible crash, sometimes not. Anyway it is bad practice. But don't forget thatauto_ptr
is designed in such way that you cannot use it straight with STL containers and algorithms: against you have to write some wrapper code. At last usingauto_ptr
with STL containers is for your own risk. For example, some implementations ofsort
will not lead to the crash while processingvector
elements, but other implementations will lead directly to the crash.This question has academic purposes. Thanks to KennyTM for providing STEP 3 crash example!
I don't have MSVC right now, but judging from the error from g++, I guess this is the reason:
auto_ptr<T>
only has a "copy constructor" which takes mutable references (§D.10.1.1[auto.ptr.cons]/2–6):But
vector::push_back
will accept a const reference (§23.3.6.1[vector.overview]/2).So it is impossible to construct an auto_ptr via push_back because no constructor takes a const reference.