为什么 auto_ptr 被弃用?

发布于 2024-09-18 15:43:53 字数 124 浏览 10 评论 0原文

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

我还想知道 auto_ptrshared_ptr 之间的区别。

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

Also I would like to know the difference between auto_ptr and shared_ptr.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

∞梦里开花 2024-09-25 15:43:53

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

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

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_ptr transfers ownership when it's assigned. unique_ptr also 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).

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

泛滥成性 2024-09-25 15:43:53

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

首先,(正如 Jerry Coffin 在他的回答中指出的)

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

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

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

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

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

从这一行开始,我将把共享/唯一 _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 支持的分配类型

  • 复制分配 (4) 罪魁祸首

现在来谈谈为什么复制分配本身如此不受欢迎的原因,我有这样的理论:

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

这种意外的行为确实令人讨厌,因此也不喜欢 auto_ptr。

(对于有意想要转让所有权的 3.1415926536% 程序员来说,C++11 为他们提供了 std::move(),这使得所有将要阅读和维护代码的实习生的意图一目了然。)

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.

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

  • auto_ptr could be replaced by shared_ptr or unique_ptr depending upon situation

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.

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.

unique_ptr : If all you are concerned is freeing memory, and the access to object is SEQUENTIAL, then go for 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 FIRST data-structure. Then either the object is destroyed after the ONE data-structure or is moved to SECOND data-structure.

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. )

Single most important reason as to why auto_ptr was deprecated in favor of smart-pointer is
assignment-semantics If 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.

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

Kind of assignments supported by unqiue_ptr

  • move assignment (1)
  • assign null pointer (2)
  • type-cast assignment (3)
  • copy assignment (deleted!) (4)

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

Kind of assignments supported by 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.

The unintended behavior is really disliked and hence the dislike for the 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.)

烟酉 2024-09-25 15:43:53

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

顺便说一句,unique_ptr实际上是auto_ptr的直接替代品,它结合了std::auto_ptrboost::scoped_ptr<的最佳功能。 /代码>。

shared_ptr can be stored inside containers. auto_ptr can't.

BTW unique_ptr is really the direct auto_ptr replacement, it combines the best features of both std::auto_ptr and boost::scoped_ptr.

旧人九事 2024-09-25 15:43:53

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

从功能上讲,C++11 的 std::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 悄悄“窃取”*ap 的所有权,将 ap 设置为 nullptr,问题就来了是这种情况很容易发生,而程序员却没有考虑到它的安全性。

例如,如果 class/struct 有一个 std::auto_ptr 成员,则创建实例的副本将release< /code> 正在复制的实例的指针:这是奇怪且危险的令人困惑的语义,因为通常复制某些内容不会修改它。类/结构作者在推理不变量和状态时很容易忽略指针的释放,因此意外地尝试在 null 时取消引用智能指针,或者只是仍然不具有所指向数据的预期访问/所有权。

Yet another take on explaining the difference....

Functionally, C++11's std::unique_ptr is 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.

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(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

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

For example, if a class/struct has a std::auto_ptr member, then making a copy of an instance will release the 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.

终遇你 2024-09-25 15:43:53

auto_ptr 不能在 STL 容器中使用,因为它的复制构造函数不满足容器的要求 可复制构造。 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

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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文