C++スマートポインタauto_ptr詳細

13144 ワード

1. auto_ptrの設計動機:
関数の操作は、次のパターンに従って行われます.
  • いくつかのリソースを取得
  • いくつかの動作
  • を実行する.
  • 取得したリソースを解放する
  • .
    これらのリソースの解放の問題に直面すると、次の2つの状況が発生します.
  • 最初に得られたリソースがローカルオブジェクトにバインドされ、関数が終了すると、これらのローカルオブジェクトの構造関数が自動的に呼び出され、自動的にこれらのリソースが解放される.
  • が最初に取得したリソースは、何らかの表示手段によって取得され、任意のオブジェクトにバインドされていないので、明示的に解放されなければならない.このような状況はしばしばポインタに発生する.

  • 例:
    1 void f()
    
    2 {
    
    3       ClassA* ptr = new ClassA();
    
    4       ...
    
    5       delete ptr;
    
    6 }    

    上記のコードの本当の問題は、いったん...のどこかで異常が発生すると、f()関数はすぐに終了し、関数の末端のdelete文を呼び出すことはありません.その結果、メモリが失われたり、リソースが失われたりする可能性があります.
     
    上記の問題の解決策の1つは、次のとおりです.
     1 void f()
    
     2 {
    
     3      ClassA*  ptr = new ClassA();
    
     4 
    
     5      try
    
     6     {
    
     7         ...  
    
     8     }
    
     9     catch(...)
    
    10     {
    
    11         delete ptr;
    
    12         throw; 
    
    13      }
    
    14      
    
    15      delete ptr;    
    
    16 }

    異常発生時にオブジェクトの削除作業を処理するために、プログラムコードは非常に複雑で煩雑になります!
    このため、スマートポインタの概念が導入されました.
    インテリジェントなポインタは、どのような状況でも、自分が破壊された限り、その指向するリソースを連帯して解放しなければならないことを保証しなければならない.スマートポインタ自体がゾーン変数なので、正常に発売されても、異常に発売されても、必ず破棄されます.auto_ptrはまさにこのポインタです.
    auto_ptrは、「その指すオブジェクト」の所有者であるポインタです.したがって、オブジェクト所有者であるauto_ptrが破棄されると、そのオブジェクトも破棄されます.auto_ptrは1つのオブジェクトに1人の所有者しかいないことを要求し、1物2主を厳禁する.(天と地の間には,それぞれ主があり,わたしの所有ではない.
    次にauto_を一例で認識しますptrの使用:
     1 #include <iostream>
    
     2 #include <string>
    
     3 #include <memory>
    
     4 
    
     5 using namespace std;
    
     6 
    
     7 class Test
    
     8 {
    
     9     public:
    
    10         Test(const string& psg);
    
    11         string getMsg();
    
    12     private:
    
    13         string msg;
    
    14 };
    
    15 
    
    16 Test::Test(const string& psg)
    
    17 {
    
    18     msg = psg;
    
    19 }
    
    20 
    
    21 string Test::getMsg()
    
    22 {
    
    23     return msg;
    
    24 }
    
    25 
    
    26 int main(void)
    
    27 {
    
    28     std::auto_ptr<Test> ptr(new Test("This is the end of the world!"));
    
    29     cout<<ptr->getMsg()<<endl;
    
    30     return 0;
    
    31 }

    auto_を初期化ptrの場合、ポインタをパラメータとしてauto_に渡します.ptrの構造関数.割り当てオペレータは使用できません.
     
    2. auto_ptr所有権の移行:auto_ptrは厳格な所有権観念を定義している.つまり、auto_ptrはその指向するオブジェクトを削除するので、このオブジェクトは絶対に他のオブジェクトに同時に「所有」されてはいけない.絶対に複数出現してはならない
    auto_ptrsは同じオブジェクトを持っています.
     
    ではauto_ptrのcopyコンストラクション関数とassignmentオペレータはどのように動作しますか?
    追加ptrのcopyコンストラクション関数とassignmentオペレータはオブジェクトの所有権を渡します!
    1     // initialize an auto_ptr with a new object
    
    2     std::auto_ptr<Test> ptr1(new Test("This is the end of the world!"));
    
    3 
    
    4     // copy the auto_ptr
    
    5     // ~ transfers ownership from ptr1 to ptr2
    
    6     std::auto_ptr<Test> ptr2(ptr1);
    
    7 
    
    8     cout<<ptr1->getMsg()<<endl;

    上のオブジェクトの所有権がptr 1からptr 2に渡されたときに、ptr 1を使用してgetMsgに行くと、「セグメントエラー」というメッセージが表示されます.
     1 #include <iostream>
    
     2 #include <string>
    
     3 #include <memory>
    
     4 
    
     5 using namespace std;
    
     6 
    
     7 class Test
    
     8 {
    
     9     public:
    
    10         Test(const string& psg,const int& id);
    
    11         ~Test();
    
    12         string getMsg();
    
    13     private:
    
    14         string msg;
    
    15         int id;
    
    16 };
    
    17 
    
    18 Test::Test(const string& psg,const int& pid)
    
    19 {
    
    20     msg = psg;
    
    21     id = pid;
    
    22 }
    
    23 
    
    24 Test::~Test()
    
    25 {
    
    26     cout<<"Delete "<<id<<" "<<endl;
    
    27 }
    
    28 
    
    29 string Test::getMsg()
    
    30 {
    
    31     return msg;
    
    32 }
    
    33 
    
    34 int main(void)
    
    35 {
    
    36     std::auto_ptr<Test> ptr1(new Test("This is ptr1",1));
    
    37     std::auto_ptr<Test> ptr2(new Test("This is ptr2",2));
    
    38     ptr2 = ptr1;
    
    39     return 0;
    
    40 }

    上のコードの結果は次のとおりです.
    1 Delete 2
    
    2 Delete 1

    ptr 2が割り当てられる前に別のオブジェクトがあり、割り当て動作が発生するとdeleteが発生し、そのオブジェクトが削除されることを示します.