1

I understand that auto_ptr cannot be used with vectors since auto_ptr does not meet the requirement of being a copy constructible. Since the auto_ptr being copied is modified, copying does not result in two exact copies thereby violating the copy constructible idiom.

Unique_ptr also seem to do the same; it modifies the object being copied - the pointer member of the object being copied is set to nullptr. Then, how is it possible to use uinque_ptr with vectors and not the auto_ptrs ?

Is my understanding correct or am I missing something here?

auto_ptr <int> autoPtr(new int);
vector < auto_ptr <int> > autoVec;
autoVec.push_back(autoPtr);         //compiler error..why?

unique_ptr <int> uniquePtr(new int);
vector < unique_ptr <int> > uniqueVec;
uniqueVec.push_back(std::move(uniquePtr));  //okay..why?
Vishal
  • 158
  • 6
  • 3
    [so you can't copy it](http://coliru.stacked-crooked.com/a/495f091f798712ab), [however you can move it](http://coliru.stacked-crooked.com/a/361fc294fb13279d) – Bryan Chen Feb 24 '15 at 05:01
  • @VxxGxx It's just that `auto_ptr` doesn't offer you any protection against being nulled out by attempted copying. Also, `auto_ptr` is deprecated. Still, that will at best give you a warning. – Cheers and hth. - Alf Feb 24 '15 at 06:34
  • @BryanChen Either we copy (through a non-const reference in auto_ptr) or move it (through a rvalue reference), the object being copied is changed. This violates the copy constructible idiom. Then what is that makes unique_ptr suitable for containers like vectors and not the auto_ptr? – Vishal Feb 24 '15 at 08:18
  • @Cheersandhth.-Alf Yes I understand the pitfalls of using auto_ptr and the extra level of safety offered by unique_ptr. But here I am trying to understand as to why unique_ptr can be used and auto_ptr cannot be used with vectors – Vishal Feb 24 '15 at 08:21
  • @VxxGxx: The "but" isn't meaningful to me, sorry. Can you demonstrate what you mean by "cannot be used with vectors" in C++11 or later. Linking to a concrete example on the net would be nice. – Cheers and hth. - Alf Feb 24 '15 at 09:53
  • @Cheersandhth.-Alf - I've edited my question to add a code snippet. The std::move() only converts lvalues to rvalues, but how does it make the unique_ptr possible to use with standard containers while auto_ptr throws a compiler error? – Vishal Feb 24 '15 at 11:58

2 Answers2

4

The problem with auto_ptr was that an operation that wasn't expected to modify an object did modify it. The copy constructor modified the source.

unique_ptr doesn't have a copy constructor. It has a move constructor. The move constructor also modifies the source, but this is expected, and it's possible for generic code to distinguish between situations that use the copy constructor and those that use the move constructor.

vector (and the other containers) didn't just magically work with unique_ptr once it was written. They had to be updated so that they could work with move-only types. This was done in C++11. It was possible to make this modification because moving and copying are different operations. It wasn't possible to do the same for auto_ptr because that class had a weird copy constructor.

Sebastian Redl
  • 69,373
  • 8
  • 123
  • 157
0

The compilation error is because of an attempt to modify the auto_ptr const& formal argument (by copying it) in the push_back implementation.

Instead of

autoVec.push_back(autoPtr);

you can do

autoVec.emplace_back( autoPtr.release() );

or more directly (not using the autoPtr variable)

autoVec.emplace_back( new int(42) );

However, while this works in a technical sense (disclaimer: code not even glanced at by any compiler) you still have the problem of auto_ptr items nulling themselves as a result of attempted copying. So this is all very very unsafe. Additionally, auto_ptr was deprecated in C++11; I do not know whether it has been altogether removed now, but that's not unlikely.

Cheers and hth. - Alf
  • 142,714
  • 15
  • 209
  • 331