为什么unique_ptr有效,但auto_ptr不适用于 STL

Why unique_ptr works but auto_ptr doesn’t with STL

提问人:anurag86 提问时间:11/9/2019 最后编辑:curiousguyanurag86 更新时间:11/10/2019 访问量:252

问:

我已经参考了很多关于这些问题的 StackOverflow 链接,其中不能很好地使用 STL 的原因是不符合可复制构造和可分配的要求(因为有一个假的复制构造函数,它基本上转移了所有权)。auto_ptrstd::auto_ptr<>auto_ptr

但是即使没有复制 ctor 和赋值运算符(它被禁用),那么如何满足可复制构造和可赋值的要求呢?unique_ptr

C++ STL 复制构造函数 unique-ptr auto-ptr

评论

0赞 chris 11/9/2019
您是否有一个需要复制但可以使用的特定示例?unique_ptr

答:

1赞 parktomatomi 11/9/2019 #1

我假设您指的是将智能指针与 STL 容器一起使用。

auto_ptr可以,但不应使用,因为它的复制构造函数可能会意外移动数据(它是在 C++11 中添加带有右值引用的移动语义之前设计的)。

unique_ptr没有复制构造函数,因此它不能在 STL 容器中简单使用。复制指针的操作将不起作用,但这就是它的安全之处。您仍然可以显式使用移动迭代器或 emplace 将不可复制的元素放入容器中。

在容器中使用的示例如下: 那么unique_ptr可以在 stl 集合中安全地使用吗?unique_ptr

评论

0赞 anurag86 11/9/2019
是的。明白了。微不足道,你的意思是“总是”吗?
0赞 parktomatomi 11/9/2019
不。只是你随便做的一些事情是行不通的.如果你是 ,你会得到一个讨厌的错误。但如果你是一个,你可能不会。有关示例,请参阅链接。vector<int>unique_ptrpush_backunique_ptremplace_back
1赞 eerorika 11/9/2019
只要参数是右值,@parktomatomi push_back就可以很好地处理unique_ptr。
8赞 Nicol Bolas 11/9/2019 #2

你把整个事情倒过来看。

在 C++98/03 中,我们得到了 .这种类型通过假装它支持复制语义来欺骗所有人,而实际上复制它所做的与复制操作非常不同。因此,任何依赖于提供复制语义的类型(如某些容器)都不能很好地获得 .当然,只有当你的代码变得功能失调时,你才会发现,而不是在编译时。auto_ptrauto_ptr

在 C++11 中,我们得到了 ,这是一个显式不提供复制语义的类型。相反,它提供移动语义,并正确地提供它们。因此,任何依赖于提供复制语义的类型的类型在给定 .unique_ptrunique_ptr

然而,之所以出现这个原因,是因为在 C++11 中添加了移动对象的概念。当新概念被添加到语言中时,现有工具(如标准库要求)通常会相对于该语言功能进行重新评估。unique_ptr

例如,以前需要复制语义的类型不一定必须保留该要求。需要复制语义的 C++98/03 容器在 C++11 中更新为仅要求(除了)从类型中移动语义。

因此,它并不能满足某些未满足的要求。而是语言更改为不再需要该要求,但仍然在撒谎,因此出于向后兼容性的考虑,我们创建了一种尊重新语言功能并且不对人们撒谎的新类型。unique_ptrauto_ptrauto_ptr

评论

1赞 anurag86 11/9/2019
您的答案值得在 stackoverflow 上发布 20 篇其他详细帖子。这就是我一直在寻找的 - 关于改变要求和 ptr 用法的标准变化。
1赞 eerorika 11/9/2019 #3

auto_ptr看起来像复制可构造/可赋值,因为它具有复制构造函数和赋值运算符。

问题在于它的复制构造函数和赋值没有实现复制语义,而是移动语义。这使得auto_ptr的接口令人惊讶,并使其在内部分配元素的容器(例如向量)中无法使用。

更糟糕的是,在向量中使用auto_ptr格式正确(没有编译错误),但没有有用的行为,这很容易导致未定义的行为(即严重的错误)。

但即使是unique_ptr也没有复制 ctor 和赋值运算符(已禁用)

unique_ptr不需要是可复制的、可构造的或可分配的。对于大多数用例来说,移动、可构造和可分配就足够了。

unique_ptr可以取代auto_ptr的所有用途,并且没有auto_ptr的问题。自 C++11 引入了对移动的unique_ptr和语言支持以来,auto_ptr已被弃用,自 C++17 起,auto_ptr已从标准库中删除。

评论

0赞 anurag86 11/9/2019
我的困惑更多的是“STL的可复制构造和可分配的要求”仍然没有被unique_ptr满足。你给出的例子“使auto_ptr的接口令人惊讶,并使其在内部分配元素的容器(如向量)中无法使用。 最终,在unique_ptr的情况下,最终结果也是一样的——即数据被移动而不是复制。auto_ptr通过复制来移动它,unqiue_ptr通过移动来移动它。那么在这种情况下,我们更喜欢什么变化unique_ptr
1赞 eerorika 11/9/2019
@anurag86 复制unique_ptr一点也不奇怪。完全可以预料到它不能被复制。如果您不这么认为,编译器会相对清楚地告诉您。
1赞 eerorika 11/9/2019
@anurag86 auto_ptr没有任何变化。这始终是一个有缺陷的设计。当C++标准化时,根本没有更好的选择。通常建议在弃用之前就避免使用它。改变的是C++语言和移动语义的引入,特别是unique_ptr类型引入语言。Unique_ptr这就是auto_ptr应该有的样子,但不可能,因为语言中没有移动语义。