100

我听说auto_ptr在 C++11 中被弃用了。这是什么原因?

我也想知道 和 之间的auto_ptr区别shared_ptr

4

5 回答 5

98

的直接替代品auto_ptr(或最接近的替代品)是unique_ptr. 就“问题”而言,它非常简单:auto_ptr在分配所有权时转移所有权。unique_ptr也转移所有权,但由于移动语义的编码和右值引用的魔力,它可以更自然地做到这一点。它也更好地“适合”标准库的其余部分(尽管公平地说,其中一些要归功于库的其余部分进行了更改以适应移动语义,而不是总是需要复制)。

名称的更改也是(IMO)一个受欢迎的更改 -auto_ptr并没有真正告诉您它试图自动化的内容,而是unique_ptr对所提供内容的相当合理(如果简洁)的描述。

于 2010-09-13T03:45:22.880 回答
36

我发现现有的答案很好,但来自指针的 PoV。IMO,一个理想的答案应该有用户/程序员的观点答案。

首先第一件事(正如杰里·科芬在他的回答中指出的那样)

  • auto_ptr 可以根据情况替换为 shared_ptr 或 unique_ptr

shared_ptr : 如果您担心资源/内存的释放,并且如果您有多个函数可以使用对象 AT-DIFFERENT 次,那么请使用 shared_ptr。

通过 DIFFERENT-Times,想想 object-ptr 存储在多个数据结构中并稍后访问的情况。多线程,当然是另一个例子。

unique_ptr :如果您只关心释放内存,并且对对象的访问是连续的,那么请使用 unique_ptr。

我的意思是,在任何时候都可以从一个上下文访问对象。例如,创建者创建并在创建后立即使用的对象。创建后,对象存储在FIRST数据结构中。然后对象要么在 ONE 数据结构之后被销毁,要么被移动到SECOND数据结构。

从这一行开始,我将共享/唯一 _ptr 称为智能指针。(auto_ptr 也是智能指针,但由于其设计存在缺陷,因此它们已被弃用,我想我将在下一行中指出,它们不应与智能指针分组。)

关于为什么不推荐使用 auto_ptr 以支持智能指针的一个最重要的原因是 赋值语义 如果不是因为这个原因,他们会将移动语义的所有新优点添加到 auto_ptr 而不是弃用它。由于赋值语义是最不喜欢的功能,他们希望该功能消失,但由于编写了使用该语义的代码(标准委员会无法更改),他们不得不放弃 auto_ptr,而不是修改它。

从链接:http ://www.cplusplus.com/reference/memory/unique_ptr/operator=/

unqiue_ptr 支持的分配类型

  • 搬家作业 (1)
  • 分配空指针 (2)
  • 类型转换分配 (3)
  • 复制作业(已删除!)(4)

来自:http ://www.cplusplus.com/reference/memory/auto_ptr/operator=/

auto_ptr 支持的分配类型

  • 抄作业(四) 罪魁祸首

现在谈到为什么复制作业本身如此不受欢迎的原因,我有这个理论:

  1. 并非所有程序员都阅读书籍或标准
  2. auto_ptr 从表面上看,向您保证对象的所有权
  3. auto_ptr 的 little-*(双关语)子句并非所有程序员都阅读,它允许将一个 auto_ptr 分配给另一个,并转移所有权。
  4. 研究表明,此行为适用于所有使用的 3.1415926535 %,在其他情况下是无意的。

意外的行为真的很不喜欢,因此不喜欢 auto_ptr。

(对于有意转移所有权的 3.1415926536% 的程序员,C++11 给了他们 std::move(),这让所有将要阅读和维护代码的实习生清楚地知道他们的意图。)

于 2013-02-24T06:12:35.630 回答
23

shared_ptr可以存放在容器内。 auto_ptr不能。

BTWunique_ptr真的是直接auto_ptr替代品,它结合了std::auto_ptr和的最佳特性boost::scoped_ptr

于 2010-09-13T03:27:21.910 回答
12

另一种解释差异的方法......

从功能上讲,C++11std::unique_ptr是“固定的” std::auto_ptr:它们都适用于 - 在执行期间的任何时间点 - 指向对象应该有一个智能指针所有者。

关键的区别在于从另一个未到期的智能指针复制构造或赋值,如下=>行所示:

   std::auto_ptr<T> ap(new T{...});       // OK - alloc/construct, up owns
   ...or...
   std::auto_ptr<T> ap(get_ap_to_T());   // OK - take expiring ownership

   ...then...
=> std::auto_ptr<T> ap2(ap);  // take un-expiring ownership ala ap3(ap.release());
   ap->xyz;  // oops... tried to use ap, expecting it to be non-NULL

   // --------------------------------------------------------------

   std::unique_ptr<T> up(new T{...});       // OK - alloc/construct, up owns
   ...or...
   std::unique_ptr<T> up = std::make_unique<T>(...);       // OK too
   ...or...
   std::unique_ptr<T> up(get_up_to_T());   // OK - take expiring ownership

   ...then...
=> std::unique_ptr<T> up2(up);  // COMPILE ERROR: can't take un-expiring ownership
=> std::unique_ptr<T> up2(std::move(up));  // EXPLICIT code allowed
=> std::unique_ptr<T> up2(up.release());   // EXPLICIT code allowed

上面,ap3 auto_ptr悄悄地“窃取”了 的所有权,设置为 a ,问题是这很容易发生,而程序员没有考虑过它的安全性*apapnullptr

例如,如果class/struct有一个std::auto_ptr成员,那么复制一个实例将release指向被复制实例的指针:这是一种奇怪且危险的语义混淆,因为通常复制某些内容不会修改它。类/结构作者在推理不变量和状态时很容易忽略指针的释放,因此在 null 时不小心尝试取消引用智能指针,或者只是仍然没有预期的指向数据的访问/所有权。

于 2015-02-12T04:21:34.923 回答
4

auto_ptr 不能在 STL 容器中使用,因为它具有不符合容器CopyConstructible要求的复制构造函数。unique_ptr 不实现复制构造函数,因此容器使用替代方法。unique_ptr 可以在容器中使用,并且对于 std 算法比 shared_ptr 更快。

#include <iostream>
#include <type_traits>
#include <vector>
#include <memory>

using namespace std;

int main() {
  cout << boolalpha;
  cout << "is_copy_constructible:" << endl;
  cout << "auto_ptr: " << is_copy_constructible< auto_ptr<int> >::value << endl;
  cout << "unique_ptr: " << is_copy_constructible< unique_ptr<int> >::value << endl;
  cout << "shared_ptr: " << is_copy_constructible< shared_ptr<int> >::value << endl;

  vector<int> i_v;
  i_v.push_back(1);
  cout << "i_v=" << i_v[0] << endl;
  vector<int> i_v2=i_v;
  cout << "i_v2=" << i_v2[0] << endl;

  vector< unique_ptr<int> > u_v;
  u_v.push_back(unique_ptr<int>(new int(2)));
  cout << "u_v=" << *u_v[0] << endl;
  //vector< unique_ptr<int> > u_v2=u_v;  //will not compile, need is_copy_constructible == true
  vector< unique_ptr<int> > u_v2 =std::move(u_v);  // but can be moved
  cout << "u_v2=" << *u_v2[0] << " length u_v: " <<u_v.size() << endl;

  vector< shared_ptr<int> > s_v;
  shared_ptr<int> s(new int(3));
  s_v.push_back(s);
  cout << "s_v=" << *s_v[0] << endl;
  vector< shared_ptr<int> > s_v2=s_v;
  cout << "s_v2=" << *s_v2[0] << endl;

  vector< auto_ptr<int> > a_v;  //USAGE ERROR

  return 0;
}

>cxx test1.cpp -o test1
test1.cpp: In function âint main()â:
test1.cpp:33:11: warning: âauto_ptrâ is deprecated (declared at /apps/hermes/sw/gcc/gcc-4.8.5/include/c++/4.8.5/backward/auto_ptr.h:87) [-Wdeprecated-declarations]
   vector< auto_ptr<int> > a_v;  //USAGE ERROR
           ^
>./test1
is_copy_constructible:
auto_ptr: false
unique_ptr: false
shared_ptr: true
i_v=1
i_v2=1
u_v=2
s_v=3
s_v2=3
于 2016-07-11T19:02:50.813 回答