C++ 为什么不推荐使用auto_ptr?

C++ 为什么不推荐使用auto_ptr?,c++,c++11,smart-pointers,auto-ptr,C++,C++11,Smart Pointers,Auto Ptr,我听说在C++11中,auto_ptr被弃用了。这是什么原因 我还想知道auto_ptr和shared_ptrshared_ptr可以存储在容器中自动\u ptr无法执行 顺便说一句,独特的ptr实际上是直接的自动ptr替换,它结合了std::auto_ptr和boost::scoped_ptr两者的最佳特性,直接替换(或最接近)是。就“问题”而言,很简单:auto_ptr在分配所有权时转移所有权unique_ptr也可以转移所有权,但由于移动语义的编码和右值引用的魔力,它可以更自然地这样做。它

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


我还想知道
auto_ptr
shared_ptr
shared_ptr
可以存储在容器中<代码>自动\u ptr无法执行


顺便说一句,独特的ptr实际上是直接的自动ptr替换,它结合了std::auto_ptr和boost::scoped_ptr两者的最佳特性,直接替换(或最接近)是。就“问题”而言,很简单:
auto_ptr
在分配所有权时转移所有权
unique_ptr
也可以转移所有权,但由于移动语义的编码和右值引用的魔力,它可以更自然地这样做。它与标准库的其余部分也“适合”得多(不过,公平地说,其中一些原因是库的其余部分更改以适应移动语义,而不是总是需要复制)


名称的改变(依我看)也是一个受欢迎的改变——
auto\u ptr
并没有告诉你多少关于它试图自动化的内容,而
unique\u ptr
是对所提供内容的一个相当合理(如果简洁)的描述。

我发现现有的答案很棒,但是从指针的角度来看。在我看来,一个理想的答案应该有用户/程序员的观点

首先要做的事(正如杰瑞·科芬在回答中指出的那样)

  • 根据具体情况,自动\u ptr可由共享\u ptr或唯一\u ptr替代
共享\u ptr:如果您担心释放资源/内存,并且如果您有多个函数可能在不同时间使用对象,请使用共享\u ptr

在不同的时候,请考虑这样一种情况,对象ptr存储在多个数据结构中,然后再进行访问。当然,多线程是另一个例子

unique\u ptr:如果您所关心的只是释放内存,并且对对象的访问是按顺序进行的,那么选择unique\u ptr

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

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

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

从链接:

unqiue\u ptr支持的作业类型

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

自动ptr支持的作业类型

  • 复印作业(4)罪魁祸首
现在谈到为什么复印作业本身如此不受欢迎,我有一个理论:

  • 并非所有程序员都阅读书籍或标准
  • 从表面上看,auto_ptr承诺您拥有该对象
  • auto_ptr的little-*(双关语)子句允许将一个auto_ptr分配给另一个auto_ptr,并转移所有权,但并非所有程序员都能阅读该子句
  • 研究表明,这种行为适用于3.1415926535%的所有使用,在其他情况下是无意的
  • 这种非故意的行为真的很不受欢迎,因此也不喜欢auto_ptr


    (3.1415926536%的程序员有意转让C++11的所有权,他们给了他们std::move(),这让所有打算阅读和维护代码的实习生都明白了他们的意图。)

    另一种解释差异的方式

    从功能上讲,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
    
    std::auto_ptr ap(…);
    std::auto_ptr ap2(get_ap_to_T());//取得到期所有权
    =>std::自动ptr ap3(ap);//取未到期的ap3(ap.release());
    ap->xyz;//哎呀。。。仍然可以尝试使用ap,希望它为非空
    std::唯一的ptr up(…);
    std::unique_ptr up2(get_up_to_T());//取得到期所有权
    =>std::unique_ptr up3(up);//编译错误:无法获取未过期的所有权
    =>std::unique_ptr up4(std::move(up));//允许显式代码
    =>std::unique_ptr up4(up.release());//允许显式代码
    
    上面,
    ap3
    悄悄地“窃取”了
    *ap
    的所有权,将
    ap
    设置为
    nullptr
    ,问题是,在程序员没有考虑到其安全性的情况下,很容易发生这种情况

    例如,如果
    /
    结构
    具有
    std::auto_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