203

随着新标准的到来(某些编译器中已经有部分可用),新类型std::unique_ptr应该是std::auto_ptr.

它们的用法是否完全重叠(所以我可以对我的代码进行全局查找/替换(不是我会这样做,但如果我这样做了))还是我应该知道阅读文档中不明显的一些差异?

此外,如果它是直接替换,为什么要给它一个新名称而不仅仅是改进std::auto_ptr

4

4 回答 4

230

您不能进行全局查找/替换,因为您可以复制一个auto_ptr(具有已知后果),但unique_ptr只能移动一个。任何看起来像的东西

std::auto_ptr<int> p(new int);
std::auto_ptr<int> p2 = p; 

至少要变成这样

std::unique_ptr<int> p(new int);
std::unique_ptr<int> p2 = std::move(p);

至于其他区别,unique_ptr可以正确处理数组(它会调用delete[],而auto_ptr会尝试调用delete.

于 2010-08-10T16:27:41.513 回答
100

std::auto_ptr并且std::unique_ptr在某些方面是不兼容的,而在其他方面则是替代品。因此,没有查找/替换还不够好。但是,在通过编译错误进行查找/替换后,应该可以修复所有问题,除了奇怪的极端情况。大多数编译错误都需要添加std::move.

  • 函数作用域变量:
    100% 兼容,只要你不将它按值传递给另一个函数。
  • 返回类型:
    不是 100% 兼容但 99% 兼容似乎没有错。
  • 函数按值参数:
    100% 兼容一个警告,unique_ptrs 必须通过std::move调用传递。这很简单,因为如果你做的不对,编译器会抱怨。
  • 参考功能参数:
    100%兼容。
  • 类成员变量:
    这个比较棘手。 std::auto_ptrs 复制语义是邪恶的。如果该类不允许复制,则std::unique_ptr替换掉。但是,如果您尝试为类提供合理的复制语义,则需要更改std::auto_ptr处理代码。这很简单,因为如果你不正确,编译器会抱怨。如果您允许在没有std::auto_ptr任何特殊代码的情况下使用成员复制课程,那么您会感到羞耻并祝您好运。

综上所述,std::unique_ptr是一个不间断的std::auto_ptr。它不允许在编译使用std::auto_ptr. 因此,如果您std::auto_ptr小心使用它,切换到std::unique_ptr应该很简单。如果您依赖std::auto_ptr' 的奇怪行为,那么无论如何您都需要重构您的代码。

于 2010-08-10T16:26:33.973 回答
37

AFAIK,unique_ptr不是直接替代品。它修复的主要缺陷是所有权的隐式转移。

std::auto_ptr<int> a(new int(10)), b;
b = a; //implicitly transfers ownership

std::unique_ptr<int> a(new int(10)), b;
b = std::move(a); //ownership must be transferred explicitly

另一方面,unique_ptr将具有全新的功能:它们可以存储在容器中。

于 2010-08-10T16:27:46.990 回答
35

Herb Sutter 对GotW #89有一个很好的解释:

与 auto_ptr 有什么关系?auto_ptr 最慷慨地描述为在 C++ 具有移动语义之前创建 unique_ptr 的勇敢尝试。auto_ptr 现在已弃用,不应在新代码中使用。

如果您在现有代码库中有 auto_ptr,当您有机会尝试将 auto_ptr 全局搜索并替换为 unique_ptr 时;绝大多数用途都是一样的,它可能会暴露(作为编译时错误)或修复(默默地)一两个你不知道的错误。

换句话说,虽然全局搜索和替换可能会暂时“破坏”您的代码,但无论如何您都应该这样做:修复编译错误可能需要一些时间,但从长远来看会为您节省更多麻烦。

于 2014-10-03T09:25:42.930 回答