5

What can I do with 'move' (r-value references) in C++11 what I can't with std::auto_ptr? (As I understand they are different implementations of one idea.)

And old question again: is std::auto_ptr so bad component?

Mat
  • 202,337
  • 40
  • 393
  • 406
Iakov Minochkin
  • 432
  • 2
  • 10
  • Regardless of the relative badness of `auto_ptr` vs. `unique_ptr`, I personally think shared pointers are the better bet. *"it can be better to simplify the contract, instead of attempting to enforce it verbatim with the type system"*. I break it down a bit in this article: http://hostilefork.com/2009/07/10/smart-pointer-casting-study/ – HostileFork says dont trust SE Dec 11 '11 at 16:34
  • [recommended watch](http://channel9.msdn.com/Shows/Going+Deep/C9-Lectures-Stephan-T-Lavavej-Standard-Template-Library-STL-9-of-n) – fredoverflow Dec 11 '11 at 16:35
  • 1
    They are definitely not different implementations of the same idea. You are probably mixing things here. They are somehow related, but as it stands this statement is wrong. – Christian Rau Dec 11 '11 at 16:41
  • 1
    @HostileFork They are not better if the objects don't need to be (or even worse, should not be) shared. Use the right tool for the right job. Spamming everything with a mess of `shared_ptr`s is surely no solution to any problem. – Christian Rau Dec 11 '11 at 16:44
  • @ChristianRau One should match a solution to the problem, naturally. But if you can rephrase a problem such that it doesn't require uniqueness you simplify the contract, and that can be helpful. This is the success of languages like Java. Programming is hard enough without making people follow a "hot potato", so don't do it unless it represents a resource that must be forced unique for a truly fundamental reason. See article. – HostileFork says dont trust SE Dec 11 '11 at 16:51
  • 3
    @HostileFork Don't use shared_ptr where unique_ptr will do. This is even more important when you're transitioning to multithreaded code. – Bartosz Milewski Dec 11 '11 at 22:47

5 Answers5

16

C++98/03 has no notion of truly "movable" classes. auto_ptr is a class with transfer-on-copy-semantics, i.e. when you make a copy, the content of the original changes (note the copy constructor with non-const argument!). This is Bad. Such a class cannot be used in the standard containers.

C++11 introduces the concept of truly movable classes thanks the the newly added notion of rvalue references. The new unique_ptr, which replaces auto_ptr entirely, is no longer copyable at all, but instead it is movable. All standard containers have been updated to attempt to move objects if possible, so it is now possible to store move-only objects in standard containers. Other examples of object which are only movable but not copyable are mutexes, locks, threads and iostreams.

To hammer in the point, compare a hypothetical, broken, C++98 piece of code with the corresponding C++11 code:

std::auto_ptr<Foo> p1(new Foo);
std::vector< std::auto_ptr<Foo> > v1;
//v1.push_back(p1);  // eeww, what is the state of p1 now? ERROR

std::unique_ptr<Foo> p2(new Foo);
std::vector<std::unique_ptr<Foo>> v2;
//v2.push_back(p2);          // Error, copying is simply not allowed
v2.push_back(std::move(p2)); // explicit; mustn't read p2 after moving it
v2.emplace_back(new Foo);    // even better ;-)
Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
5

The problem with std::auto_ptr is that it has copy operations which works like move operations. Therefore algorithms which work with copy operations can work on auto_ptr, but they don't behave as expected, since copied from objects have changed. As such auto_ptr can't be used with STL containers, however code which tries to do so will compile, but fail to work at runtime.

std::unique_ptr on the other hand doesn't have copy operations, but is only moveable instead. Therefore algorithms which copy std::unique_ptr will fail to compile when they should operate on std::unique_ptr. If something uses move operations, it doesn't expect the source of the move operation to remain the same, so no confusion there.

So basically it comes down to the operations working as is expected for a C++ object (or not).

Grizzly
  • 19,595
  • 4
  • 60
  • 78
2

One big difference is rvalue references (and assorted move optimizations) are automatically inferred/deducted from the calling context, whereas you need to create auto_ptr's manually at the call site.

Macke
  • 24,812
  • 7
  • 82
  • 118
2

auto_ptr is fundamentally broken, and rvalue references aren't. It's just that simple.

Puppy
  • 144,682
  • 38
  • 256
  • 465
2

What can I do with 'move' (r-value references) in C++11 what I can't with std::auto_ptr?

The very most important benefit of move, unique_ptr, etc, over auto_ptr is what you can't do, but can with auto_ptr.

This link explains the rationale to the committee for deprecating auto_ptr. It contains this conclusion:

Conclusion:

One should not move from lvalues using copy syntax. Other syntax for moving should be used instead. Otherwise generic code is likely to initiate a move when a copy was intended.

For details on how this conclusion was reached, read the link.

Howard Hinnant
  • 206,506
  • 52
  • 449
  • 577