为什么auto_ptr被弃用?

时间:2010-09-13 03:23:48

标签: c++ c++11 smart-pointers auto-ptr

我听说在C ++ 11中不推荐使用auto_ptr。这是什么原因?

另外,我想知道auto_ptrshared_ptr之间的区别。

5 个答案:

答案 0 :(得分:84)

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

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

答案 1 :(得分:32)

我发现现有的答案很棒,但是从指针的PoV中可以看出。 IMO,一个理想的答案应该有用户/程序员的观点答案。

第一件事(正如Jerry Coffin在答案中指出的那样)

  • auto_ptr可以替换为shared_ptr或unique_ptr,具体取决于具体情况

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

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

unique_ptr:如果您只关心释放内存,并且对对象的访问是SEQUENTIAL,那么请转到unique_ptr。

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

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

  

为什么auto_ptr被弃用以支持智能指针的最重要的原因是    assignment-semantics 如果不是因为这个原因,他们会将所有移动语义的新东西添加到auto_ptr而不是弃用它。由于赋值语义是最不受欢迎的特性,他们希望该特性消失,但由于编写的代码使用了这种语义,(标准委员会无法改变),他们不得不放弃auto_ptr,而不是修改它。

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

unqiue_ptr支持的分配类型

  • 移动作业(1)
  • 指定空指针(2)
  • type-cast assignment(3)
  • 复制作业(删除!)(4)

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

auto_ptr支持的分配类型

  • 复制作业(4)罪魁祸首

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

  1. 并非所有程序员都阅读书籍或标准
  2. auto_ptr就在它面前,承诺你拥有对象
  3. auto_ptr的little- *(双关语),子句,所有程序员都没有读取,允许将一个auto_ptr分配给另一个,并转移所有权。
  4. 研究表明,此行为适用于所有使用情况的3.1415926535%,而在其他情况下则无意。
  5. 非预期的行为真的不受欢迎,因此不喜欢auto_ptr。

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

答案 2 :(得分:21)

shared_ptr可以存储在容器中。 auto_ptr不能。

BTW unique_ptr实际上是直接auto_ptr替代品,它结合了std::auto_ptrboost::scoped_ptr的最佳功能。

答案 3 :(得分:10)

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

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

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

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

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

在上方,ap3悄悄地“窃取”了*ap的所有权,将ap设置为nullptr,问题是如果没有程序员就会轻易发生考虑到它的安全性。

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

答案 4 :(得分:3)

auto_ptr cannot be used in STL containers because it has a copy constructor that does not meet requirements of container CopyConstructible. unique_ptr does not implement a copy constructor, so containers use alternate methods. unique_ptr can be used in containers and is faster for std algorithms than 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