100

auto_ptrC++11では非推奨になると聞きました。これの理由は何ですか?

また、との違いを知りたいauto_ptrですshared_ptr

4

5 に答える 5

98

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

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

于 2010-09-13T03:45:22.880 に答える
36

私は既存の答えが素晴らしいと思いましたが、ポインターの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データ構造に格納されます。次に、オブジェクトは1つのデータ構造の後で破棄されるか、2番目のデータ構造に移動されます。

この行から、共有/一意の_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のlittle-*(しゃれを意図した)句は、すべてのプログラマーによって読み取られるわけではなく、あるauto_ptrを別のauto_ptrに割り当てることを許可し、所有権を譲渡します。
  4. 調査によると、この動作はすべての使用量の3.1415926535%を対象としており、他の場合は意図されていません。

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

(所有権を意図的に譲渡したいプログラマーの3.1415926536%に対して、C++11はstd::move()を与えました。これにより、コードを読んで維持しようとするすべてのインターンにとって、意図が明確になりました。)

于 2013-02-24T06:12:35.630 に答える
23

shared_ptrコンテナ内に保管できます。 auto_ptrできません。

ところでunique_ptr、実際には直接の代替品であり、とauto_ptrの両方の最高の機能を組み合わせています。std::auto_ptrboost::scoped_ptr

于 2010-09-13T03:27:21.910 に答える
12

違いを説明するさらに別の見方...

機能的には、C ++ 11std::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ままにします。問題は、プログラマーがその安全性について考えずに、簡単に発生する可能性があることです。apnullptr

たとえば、class/structstd::auto_ptrメンバーがある場合、インスタンスのコピーを作成すると、コピーされるインスタンスreleaseからのポインタになります。通常、何かをコピーしても変更されないため、これは奇妙で危険な混乱を招くセマンティクスです。クラス/構造体の作成者は、不変条件と状態について推論するときにポインターの解放を見落としがちであり、その結果、nullのときに誤ってスマートポインターを逆参照しようとしたり、ポイントされたデータのアクセス/所有権を期待していなかったりします。

于 2015-02-12T04:21:34.923 に答える
4

auto_ptrは、コンテナーCopyConstructibleの要件を満たさないコピーコンストラクターを持っているため、STLコンテナーでは使用できません。unique_ptrはコピーコンストラクターを実装しないため、コンテナーは代替メソッドを使用します。unique_ptrはコンテナーで使用でき、shared_ptrよりもstdアルゴリズムの方が高速です。

#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
于 2016-07-11T19:02:50.813 に答える