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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3697686/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 13:30:07  来源:igfitidea点击:

Why is auto_ptr being deprecated?

c++c++11smart-pointersauto-ptr

提问by brett

I heard auto_ptris being deprecated in C++11. What is the reason for this?

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

Also I would like to know the difference between auto_ptrand shared_ptr.

此外,我想知道的区别auto_ptrshared_ptr

采纳答案by Jerry Coffin

The direct replacement for auto_ptr(or the closest thing to one anyway) is unique_ptr. As far as the "problem" goes, it's pretty simple: auto_ptrtransfers ownership when it's assigned. unique_ptralso transfers ownership, but thanks to codification of move semantics and the magic of rvalue references, it can do so considerably more naturally. It also "fits" with the rest of the standard library considerably better (though, in fairness, some of that is thanks to the rest of the library changing to accommodate move semantics instead of always requiring copying).

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

The change in name is also (IMO) a welcome one -- auto_ptrdoesn't really tell you much about what it attempts to automate, whereas unique_ptris a fairly reasonable (if terse) description of what's provided.

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

回答by Ajeet Ganga

I found the existing answers great, but from the PoV of the pointers. IMO, an ideal answer should have the user/programmer's perspective answer.

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

First thing first (as pointed by Jerry Coffin in his answer)

首先是第一件事(正如 Jerry Coffin 在他的回答中指出的那样)

  • auto_ptr could be replaced by shared_ptr or unique_ptr depending upon situation
  • auto_ptr 可以根据情况替换为 shared_ptr 或 unique_ptr

shared_ptr :If you are concerned about freeing of resource/memory AND if you have more than one function that could be using the object AT-DIFFERENT times, then go with shared_ptr.

shared_ptr :如果您担心资源/内存的释放,并且如果您有多个函数可以在不同时间使用对象,那么请使用 shared_ptr。

By DIFFERENT-Times, think of a situation where the object-ptr is stored in multiple data-structure and later accessed. Multiple threads, of course is another example.

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

unique_ptr :If all you are concerned is freeing memory, and the access to object is SEQUENTIAL, then go for unique_ptr.

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

By SEQUENTIAL, I mean, at any point object will be accessed from one context. E.g. a object that was created, and used immediately after creation by the creator. After creation the object is stored in FIRSTdata-structure. Then either the object is destroyed after the ONE data-structure or is moved to SECONDdata-structure.

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

From this line, I will refer shared/unique _ptr as smart-pointers. (auto_ptr is also smart-pointer BUT because of flaws in it's design,for which they are being deprecated, and which I think I will point out in next lines, they should not be grouped with smart-pointer. )

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

Single most important reason as to why auto_ptr was deprecated in favor of smart-pointer is assignment-semanticsIf it wasn't for that reason, they would have added all the new goodies of move semantics to the auto_ptr instead of deprecating it. Since the assignment-semantics was most-disliked feature, they wanted that feature to go away, but since there is code written that uses that semantics, (which standards-committee can not change), they had to let go of auto_ptr, instead of modifying it.

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

From the link : http://www.cplusplus.com/reference/memory/unique_ptr/operator=/

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

Kind of assignments supported by unqiue_ptr

unqiue_ptr 支持的赋值类型

  • move assignment (1)
  • assign null pointer (2)
  • type-cast assignment (3)
  • copy assignment (deleted!) (4)
  • 移动任务 (1)
  • 分配空指针 (2)
  • 类型转换分配 (3)
  • 复制作业(已删除!)(4)

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

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

Kind of assignments supported by auto_ptr

auto_ptr 支持的赋值类型

  • copy assignment (4) culprit
  • 抄作业(四) 罪魁祸首

Now coming to the reason WHY the copy assignment itself was so disliked, I have this theory :

现在谈到为什么副本分配本身如此不受欢迎的原因,我有这个理论:

  1. Not all programmers read books or standards
  2. auto_ptr on the face of it, promises you ownership of the object
  3. the little-* (pun intended), clause of the auto_ptr, which is not read by all the programmers, allows, assignment of one auto_ptr to another, and transfers the ownership.
  4. Research has shown this behavior is intended for 3.1415926535 % of all usage, and unintended in other cases.
  1. 并非所有程序员都阅读书籍或标准
  2. auto_ptr 从表面上看,向您保证对象的所有权
  3. 并非所有程序员都阅读的 auto_ptr 的 little-*(双关语)子句允许将一个 auto_ptr 分配给另一个,并转移所有权。
  4. 研究表明,这种行为适用于所有使用的 3.1415926535 %,在其他情况下是无意的。

The unintended behavior is really disliked and hence the dislike for the auto_ptr.

真的不喜欢这种意外行为,因此也不喜欢 auto_ptr。

(For the 3.1415926536% of programmers who intentionally wants to transfer the ownership C++11 gave them std::move(), which made their intention crystal clear for all the interns who are going to read and maintain the code.)

(对于 3.1415926536% 有意转让所有权的程序员而言,C++11 为他们提供了 std::move(),这让所有要阅读和维护代码的实习生都清楚他们的意图。)

回答by Ben Voigt

shared_ptrcan be stored inside containers. auto_ptrcan't.

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

BTW unique_ptris really the direct auto_ptrreplacement, it combines the best features of both std::auto_ptrand boost::scoped_ptr.

顺便说一句unique_ptr,确实是直接auto_ptr替代品,它结合了std::auto_ptr和的最佳功能boost::scoped_ptr

回答by Tony Delroy

Yet another take on explaining the difference....

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

Functionally, C++11's std::unique_ptris the "fixed" std::auto_ptr: both of them are suitable when - at any point in time during execution - there should be a single smart-pointer owner for a pointed-to object.

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

The crucial difference is in copy-construction or assignment from another un-expiring smart pointer, shown on the =>lines below:

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

   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

Above, ap3quietly "steals" ownership of *ap, leaving apset to a nullptr, and the problem is that can happen too easily, without the programmer having thought through its safety.

上面,ap3悄悄地“窃取”了*ap, 的所有权,将apset留给了nullptr,问题是这很容易发生,程序员没有考虑过它的安全性。

For example, if a class/structhas a std::auto_ptrmember, then making a copy of an instance will releasethe pointer from the instance being copied: that's weird and dangerously confusing semantics as usually copying something doesn't modify it. It's easy for the class/struct author to overlook the release of the pointer when reasoning about invariants and state, and consequently accidentally attempt to dereference smart-pointer while null, or just not still have expected access/ownership of the pointed-to data.

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

回答by edW

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.

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 aint main()a:
test1.cpp:33:11: warning: aauto_ptra 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