auto_ptrが廃止されるのはなぜですか?


回答:


91

の直接置換auto_ptr(またはいずれにせよ最も近いもの)はunique_ptrです。「問題」に関する限り、それは非常に単純ですauto_ptr。割り当てられたときに所有権を譲渡します。unique_ptrは所有権も譲渡しますが、移動セマンティクスの体系化と右辺値参照の魔法のおかげで、かなり自然にそうすることができます。また、標準ライブラリの他の部分とかなりよく適合します(公平に言えば、一部のライブラリは、常にコピーを必要とするのではなく、移動セマンティクスに対応するように変更されたライブラリのおかげです)。

名前の変更も(IMO)歓迎すべきものです- auto_ptrそれが自動化しようとしていることについてはあまり説明しませんunique_ptrが、何が提供されているかについては(合理的であれば)かなり合理的な説明です。


24
auto_ptr名前に関するメモ:autoは自動変数のように自動を提案し、それがauto_ptr行う1つのことを指します。
Vincenzo Pii

13
詳細情報:非推奨の公式の根拠はauto_ptr次のとおり
ハワード

@HowardHinnant興味深いドキュメント!std :: sort()にstd :: unique_ptrが必要に応じて移動セマンティクスを使用するように特殊化されているという意味では奇妙です。ドキュメントに記載されているコピーの問題を修正するために、なぜstd :: sort()をstd :: auto_ptrに特化できないのかと思います。前もって感謝します。
Hei

2
@Hei: std::sortの専門分野はありませんunique_ptr。代わりに、コピーしないように再指定されました。だから、auto_ptr実際に現代で動作しsortます。しかし++ 98/03 Cは、sortここでの単なる一例アルゴリズムです: 任意のそのコピーの構文を想定して、一般的なアルゴリズム(STD-提供またはユーザーが記述したが)で使用する場合はコピー・セマンティクスは、おそらく実行時エラーになります持っているauto_ptrので、auto_ptr静かに移動コピー構文。問題は単なる問題よりもはるかに大きなものですsort
Howard Hinnant

35

既存の回答は素晴らしいと思いましたが、ポインターのPoVからです。IMO、理想的な答えは、ユーザー/プログラマーの視点の答えを持つ必要があります。

まず最初に(ジェリー・コフィンが彼の答えで指摘したように)

  • auto_ptrは状況に応じてshared_ptrまたはunique_ptrに置き換えることができます

shared_ptr: リソース/メモリの解放が心配であり、オブジェクトをAT-DIFFERENT回使用している可能性のある関数が複数ある場合は、shared_ptrを使用します。

DIFFERENT-Timesによって、object-ptrが複数のデータ構造に格納され、後でアクセスされる状況を考えてみてください。もちろん、複数のスレッドが別の例です。

unique_ptr:心配しているのがメモリの解放だけで、オブジェクトへのアクセスがSEQUENTIALの場合、unique_ptrを使用します。

SEQUENTIALとは、ある時点でオブジェクトが1つのコンテキストからアクセスされることを意味します。たとえば、作成され、作成者が作成した直後に使用されたオブジェクト。作成後、オブジェクトはFIRSTデータ構造に格納されます。次に、オブジェクトはONEデータ構造の後で破棄されるか、SECONDデータ構造に移動されます。

この行から、共有/一意の_ptrをスマートポインターと呼びます。(auto_ptrもスマートポインターですが、その設計上の欠陥のため、これらは非推奨になり、次の行で指摘するように、スマートポインターとグループ化しないでください。)

auto_ptrがスマートポインターの代わりに廃止された理由に関する最も重要な理由の1つは、 割り当てセマンティクス です。その理由がなかった場合、auto_ptrには、廃止予定ではなく、すべての新しい移動セマンティクスが追加されています。割り当てセマンティクスは最も嫌われる機能だったので、その機能を廃止したかったのですが、そのセマンティクスを使用するコードが記述されているため(標準委員会は変更できません)、代わりにauto_ptrを手放さなければなりませんでしたそれを修正する。

リンクから:http : //www.cplusplus.com/reference/memory/unique_ptr/operator=/

unqiue_ptrでサポートされる割り当ての種類

  • 移動割り当て(1)
  • nullポインタを割り当てます(2)
  • 型キャスト割り当て(3)
  • 割り当てのコピー(削除!)(4)

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

auto_ptrでサポートされる割り当ての種類

  • コピー割り当て(4) 犯人

コピーの割り当て自体がとても嫌われた理由に今、私はこの理論を持っています:

  1. すべてのプログラマーが本や標準を読むわけではない
  2. その表面のauto_ptrは、オブジェクトの所有権を約束します
  3. すべてのプログラマーによって読み取られるわけではない、auto_ptrのlittle- *(意図された)句は、1つのauto_ptrを別のauto_ptrに割り当て、所有権を転送します。
  4. 調査によると、この動作はすべての使用の3.1415926535%を対象としており、その他の場合は意図されていないことが示されています。

意図しない動作は本当に嫌われているため、auto_ptrは嫌いです。

(所有権を意図的に譲渡したいプログラマの3.1415926536%のために、C ++ 11はstd :: move()を提供しました。これにより、コードを読んで保守するすべてのインターンが意図を明確にしました。)


1
同じオブジェクトを指す2つの値が必要になることはないのでauto_ptr(共有の所有権が与えられないため、最初に死んだ値が他の値に致命的な遺産を残します。これはunique_ptr使用法についても当てはまります)、意図したことを提案できますか?残りの96.8584073465%の使用率?
Marc van Leeuwen、2014年

それらのすべてについて話すことはできませんが、おそらく、オブジェクトの所有権が移動されて おり、単に複製されているだけではなく、間違っていると考えているでしょう。
Ajeet Ganga 2014

@AjeetGanga次のフレーズ「リトル-*(しゃれた意図)」では、「しゃれた意図」として言及しました。このフレーズは私にとって新しいものであり、とにかくググって、ここで意図的に行われたジョークがあることを知りました。ここでその冗談は何ですか?それを知りたいだけです。
VINOTH ENERGETIC

@AjeetGangaあなたは、「すべてのプログラマーによって読み取られるのではなく、auto_ptrの別のauto_ptrへの割り当て、および所有権の転送を許可するauto_ptrの句であるlittle- *(しゃれ意図)」のように述べました。整数へのaおよ​​びbとして2つの自動ptrがあるとしましょう。*a=*b;ここではbの値のみがaにコピーされるので、割り当てを行っています。私はaとbの両方の所有権がまだ同じ人であることを願っています。所有権が移るようにあなたは述べました。いかがですか?
VINOTH ENERGETIC

@VINOTHENERGETIC Ajeetは、auto_ptrオブジェクト自体への割り当てについて話していました。指摘された値への割り当て、またはその値からの割り当ては、所有権に影響を与えず、関連性もありません。まだ使用していないといいのですがauto_ptr
underscore_d 2017年

23

shared_ptrコンテナ内に収納できます。 auto_ptrできません。

ところでunique_ptr、本当に直接的でauto_ptr置き換え、それは両方の長所を兼ね備えstd::auto_ptrboost::scoped_ptr


11

違いを説明するもう一つの方法...

機能的には、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/ structstd::auto_ptrメンバーが含まれている場合、インスタンスのコピーを作成すると、コピーされるインスタンスreleaseからのポインターがコピーされます。クラス/構造体の作成者が不変条件と状態について推論するときにポインターのリリースを見落とし、その結果、誤ってnullの間にスマートポインターを逆参照しようとしたり、指摘されたデータへのアクセス/所有権をまだ期待していないのは簡単です。


auto_ptrが所有権を静かに "盗み" +1
camino

3

auto_ptrには、コンテナーCopyConstructibleの要件を満たさないコピーコンストラクターがあるため、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
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.