'move'(右值引用)在C++11中相比于 std::auto_ptr
,有哪些更加强大的功能?(我理解它们是同一种思想的不同实现。)
另一个老问题: std::auto_ptr
是否真的是一个糟糕的组件?
'move'(右值引用)在C++11中相比于 std::auto_ptr
,有哪些更加强大的功能?(我理解它们是同一种思想的不同实现。)
另一个老问题: std::auto_ptr
是否真的是一个糟糕的组件?
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 ;-)
std::auto_ptr
存在的问题在于它的复制操作类似于移动操作。因此,使用复制操作的算法可以用于auto_ptr
,但由于复制自对象已经改变,所以它们不会像预期那样运行。因此,auto_ptr
不能与STL容器一起使用,然而试图这样做的代码将编译,但在运行时无法正常工作。std::unique_ptr
没有复制操作,只能进行移动操作。因此,将复制std::unique_ptr
的算法将在应该操作std::unique_ptr
时无法编译。如果某些东西使用移动操作,则不希望移动操作的源保持不变,因此不会有混淆。一个重要的区别是右值引用(和相关的移动优化)会自动从调用上下文中推断/推导出来,而您需要在调用站点手动创建auto_ptr。
auto_ptr
是基本上是有问题的,而右值引用则不是。就是这么简单。
auto_ptr
还是unique_ptr
,我个人认为共享指针是更好的选择。*"有时候,简化契约可能比试图通过类型系统逐字强制执行更好"*. 我在这篇文章中详细阐述了这一点:http://hostilefork.com/2009/07/10/smart-pointer-casting-study/ - HostileFork says dont trust SEshared_ptr
肯定不是任何问题的解决方案。 - Christian Rau