std::move和std::auto_ptr有何区别?

5

'move'(右值引用)在C++11中相比于 std::auto_ptr,有哪些更加强大的功能?(我理解它们是同一种思想的不同实现。)

另一个老问题: std::auto_ptr 是否真的是一个糟糕的组件?


无论是auto_ptr还是unique_ptr,我个人认为共享指针是更好的选择。*"有时候,简化契约可能比试图通过类型系统逐字强制执行更好"*. 我在这篇文章中详细阐述了这一点:http://hostilefork.com/2009/07/10/smart-pointer-casting-study/ - HostileFork says dont trust SE
推荐观看:http://channel9.msdn.com/Shows/Going+Deep/C9-Lectures-Stephan-T-Lavavej-Standard-Template-Library-STL-9-of-N - fredoverflow
1
它们绝对不是同一想法的不同实现。你可能在混淆事情。它们有些相关,但就目前而言,这个说法是错误的。 - Christian Rau
1
@HostileFork 如果对象不需要被共享(甚至更糟的是,不应该被共享),那么它们并不比其他工具更好。用正确的工具解决正确的问题。在所有问题上滥用shared_ptr肯定不是任何问题的解决方案。 - Christian Rau
@ChristianRau 一个人应该自然地将解决方案与问题匹配。但是,如果您可以重新表述问题,使其不需要独特性,那么您可以简化合同,这可能会有所帮助。这就是Java等语言成功的原因。编程已经很难了,不要让人们遵循“烫手山芋”,除非它代表必须强制唯一的资源,以确保真正的基本原因。请参见文章。 - HostileFork says dont trust SE
3
@HostileFork 在可以使用unique_ptr的情况下,不要使用shared_ptr。当你转换到多线程代码时,这一点更加重要。 - Bartosz Milewski
5个回答

16

C++98/03没有真正“可移动”的类的概念。 auto_ptr 是一个具有传递复制语义的类,即当您进行复制时,原始内容会更改(请注意具有非常量参数的复制构造函数!)。 这是不好的。这样的类不能用于标准容器。

C++11引入了真正可移动类的概念,得益于新添加的右值引用概念。全新的unique_ptr完全取代了auto_ptr,它不能被复制,但可以被移动。 所有标准容器都已更新以尝试移动对象(如果可能),因此现在可以将仅限移动而不可复制的对象存储在标准容器中。其他仅限移动而不可复制的对象的示例包括互斥锁、锁定、线程和输入/输出流。

为了强调这一点,比较一下假设的、损坏的C++98代码与相应的C++11代码:

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 ;-)

5
std::auto_ptr存在的问题在于它的复制操作类似于移动操作。因此,使用复制操作的算法可以用于auto_ptr,但由于复制自对象已经改变,所以它们不会像预期那样运行。因此,auto_ptr不能与STL容器一起使用,然而试图这样做的代码将编译,但在运行时无法正常工作。
另一方面,std::unique_ptr没有复制操作,只能进行移动操作。因此,将复制std::unique_ptr的算法将在应该操作std::unique_ptr时无法编译。如果某些东西使用移动操作,则不希望移动操作的源保持不变,因此不会有混淆。
因此,基本上它归结为操作按照C++对象的预期方式运行(或者不是)。

2

一个重要的区别是右值引用(和相关的移动优化)会自动从调用上下文中推断/推导出来,而您需要在调用站点手动创建auto_ptr。


2

auto_ptr 是基本上是有问题的,而右值引用则不是。就是这么简单。


1
我想说一个更委婉的说法是,“auto_ptr实现了非标准语义,使其有限的实用性”。 - Kerrek SB
为了遵守政治正确,我们不会翻译“那听起来像基督教”。为什么你不解释一下你所声称的事态是什么? - Johannes Schaub - litb
@Johannes:他问这是否不好。答案是确实如此。 - Puppy

2
在C++11中,moveunique_ptr等的最大优点在于与auto_ptr相比,你不能做的事情,但是你可以用auto_ptr来实现。这篇文章解释了委员会废除auto_ptr的原因。其中包括以下结论:

结论:

不应该使用复制语法从左值移动(move)。应该使用其他移动语法。否则,通用代码可能会在意图进行复制时误操作为移动。

有关如何得出这一结论的详细信息,请阅读此链接

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接