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


文書ディレクトリ
  • unique_ptr記述
  • 声明
  • 作用
  • 関数ポインタ記述
  • まとめ
  • unique_ptr記述
    宣言
    ヘッダファイル:テンプレートクラス:
  • デフォルトタイプtemplate > class unique_ptr
  • 配列タイプtemplate class unique_ptr;
  • さぎょう
    shared_とptrの最大の違いはunique_ですptrは同じアドレスを共有することができず,アドレスを独占している.unique_ptrオブジェクトのライフサイクルが終了すると、参照されるアドレス空間も解放されます.
    unique_ptrオブジェクトは主に2つの部分を含む
  • メモリポインタ:主にオブジェクトのアドレス空間を管理するために使用されます.コンストラクション関数に割り当てられたアドレスであり、割り当て演算子およびresetメンバー関数によってアドレス空間の再指向を行うことができる.getとreleaseメンバー変数を単独でアクセスしてunique_を取得できます.ptrオブジェクトのアドレス空間.
  • ストレージ削除器:削除器は呼び出すことができるオブジェクトです.主にunique_を削除するために使用されます.ptrオブジェクトのアドレス空間.現在のオブジェクトの変更は、付与演算子を使用してget_で行うことができます.deleterメンバー関数は単独でアクセスします.

  • 関数ポインタの説明
  • コンストラクタ
    //unique_ptr constructor example
    #include 
    #include 
    
    int main () {
      std::default_delete<int> d;
      //    
      std::unique_ptr<int> u1;
      //  null     ,    
      std::unique_ptr<int> u2 (nullptr);
      //     
      std::unique_ptr<int> u3 (new int);
      //         ,           ,     
      std::unique_ptr<int> u4 (new int, d);
      //         ,                   ,  unique_ptr    
      std::unique_ptr<int> u5 (new int, std::default_delete<int>());
      std::unique_ptr<int> u6 (std::move(u5));
      std::unique_ptr<int> u7 (std::move(u6));
      std::unique_ptr<int> u8 (std::auto_ptr<int>(new int));
    
      std::cout << "u1: " << (u1?"not null":"null") << '
    '
    ; std::cout << "u2: " << (u2?"not null":"null") << '
    '
    ; std::cout << "u3: " << (u3?"not null":"null") << '
    '
    ; std::cout << "u4: " << (u4?"not null":"null") << '
    '
    ; std::cout << "u5: " << (u5?"not null":"null") << '
    '
    ; std::cout << "u6: " << (u6?"not null":"null") << '
    '
    ; std::cout << "u7: " << (u7?"not null":"null") << '
    '
    ; std::cout << "u8: " << (u8?"not null":"null") << '
    '
    ; return 0; }
    の出力は、
    u1: null
    u2: null
    u3: not null
    u4: not null
    u5: null
    u6: null
    u7: not null
    u8: not null
    
  • である.
  • 構造関数;オブジェクトが空のunique_の場合ptr、すなわちget()=nullptrを使用すると、構造関数が機能しなくなります.そうしないと、get_deleter()関数のように
    // unique_ptr destructor example
    #include 
    #include 
    
    int main () {
      auto deleter = [](int*p){
        delete p;
        std::cout << "[deleter called]
    "
    ; }; std::unique_ptr<int,decltype(deleter)> foo (new int,deleter); std::cout << "foo " << (foo?"is not":"is") << " empty
    "
    ; return 0; // [deleter called] }
    が出力します.
    foo is not empty
    [deleter called]
    
  • です.
  • operator=
    // unique_ptr::operator= example
    #include 
    #include 
    
    int main () {
      std::unique_ptr<int> foo;
      std::unique_ptr<int> bar;
    
      foo = std::unique_ptr<int>(new int (101));  // rvalue
    	
      //std::move    foo             bar,      foo   empty
      //     std::move     unique_ptr               
      bar = std::move(foo);                       // using std::move
    
      std::cout << "foo: ";
      if (foo) std::cout << *foo << '
    '
    ; else std::cout << "empty
    "
    ; std::cout << "bar: "; if (bar) std::cout << *bar << '
    '
    ; else std::cout << "empty
    "
    ; return 0; }
    出力:
    foo: empty
    bar: 101
    
  • std :: unique_ptr :: getメンバー、変更メンバー関数は管理されたunique_ptrオブジェクトを返します.この関数の呼び出しはunique_を使用しません.ptrリリースポインタの所有権(すなわち、管理データをある時点で削除する責任を負います).このため、この関数が返す値は、新しい管理ポインタを構築するために使用できません.ポインタをアクティブに格納し、正常にリリースできるようにするには、release()メンバー関数
    // unique_ptr::get vs unique_ptr::release
    #include 
    #include 
    
    int main () {
                                               // foo   bar    p
                                               // ---   ---   ---
      std::unique_ptr<int> foo;                // null
      std::unique_ptr<int> bar;                // null  null
      int* p = nullptr;                        // null  null  null
    
      foo = std::unique_ptr<int>(new int(10)); // (10)  null  null
      //    std::move  foo           bar
      std::cout << "foo: " << foo.get() << std::endl;
      bar = std::move(foo);                    // null  (10)  null
      std::cout << "foo: " << foo.get() << std::endl;
      std::cout << "bar: " << bar.get() << std::endl;
      p = bar.get();                           // null  (10)  (10)
      *p = 20;                                 // null  (20)  (20)
      p = nullptr;                             // null  (20)  null
    
      foo = std::unique_ptr<int>(new int(30)); // (30)  (20)  null
      p = foo.release();                       // null  (20)  (30)
      *p = 40;                                 // null  (20)  (40)
    
      std::cout << "foo: ";
      if (foo) std::cout << *foo << '
    '
    ; else std::cout << "(null)
    "
    ; std::cout << "bar: "; if (bar) std::cout << *bar << '
    '
    ; else std::cout << "(null)
    "
    ; std::cout << "p: "; if (p) std::cout << *p << '
    '
    ; else std::cout << "(null)
    "
    ; std::cout << '
    '
    ; delete p; // the program is now responsible of deleting the object pointed to by p // bar deletes its managed object automatically return 0; }
    を使用して、
    optionscompilationexecution
    foo: 0x817a10
    foo: 0
    bar: 0x817a10
    foo: (null)
    bar: 20
    p: 40
    
  • を出力します.
  • std :: unique_ptr :: release現在のunique_は、メンバー関数の戻り値および空のポインタを変更することによって解放される.ptrポインタの所有権現在の呼び出しは管理オブジェクトを破壊することはなく、メンバー関数を変更してもオブジェクトは削除されず、他のエンティティがいつかオブジェクトを削除する必要があります.オブジェクトを強制的に削除するには、resetまたは付与演算子(std::move)
    // unique_ptr::release example
    #include 
    #include 
    
    int main () {
      std::unique_ptr<int> auto_pointer (new int);
      int * manual_pointer;
    
      *auto_pointer=10;
        std::cout << " auto_pointer " << auto_pointer.get() << std::endl;
      manual_pointer = auto_pointer.release();
      std::cout << " auto_pointer " << auto_pointer.get() << std::endl;
      std::cout << " manual_pointer " << manual_pointer<< std::endl;
      // (auto_pointer is now empty)
    
      std::cout << "manual_pointer points to " << *manual_pointer << '
    '
    ; delete manual_pointer; return 0; }
    を使用して、次のように出力する必要があります.
    auto_pointer 0x3afffa0
     auto_pointer 0
     manual_pointer 0x3afffa0
    manual_pointer points to 10
    
  • std::unique_ptr::reset void reset (pointer p = pointer()) noexcept;現在のunique_ptrオブジェクトを破壊し、その所有権pを取得する.pが空である場合、現在のunique_ptrオブジェクトも空である.現在のオブジェクトを解放し、オブジェクトが指すアドレス空間および内容を破壊しない場合、releaseメンバー関数
    // unique_ptr::reset example
    #include 
    #include 
    
    int main () {
      std::unique_ptr<int> up;  // empty
    
      //reset   up             ,     up  ,        
      up.reset (new int);       // takes ownership of pointer
      //              null         
      std::cout << *up << " " << up.get() << '
    '
    ; *up=5; std::cout << *up << " " << up.get() << '
    '
    ; up.reset (new int); // deletes managed object, acquires new pointer *up=10; std::cout << *up << " " << up.get() << '
    '
    ; up.reset(); // deletes managed object return 0; }
    を使用して、
    0 0xd7dc70
    5 0xd7dc70
    10 0xd7dc90
    
  • が出力する.
  • std::unique_ptr::swapは対象空間及び内容を交換し、アドレス空間
    // unique_ptr::swap example
     #include 
     #include 
     
     int main () {
       std::unique_ptr<int> foo (new int(10));
       std::unique_ptr<int> bar (new int(20));
       
       std::cout << "foo: " << *foo << " " << foo.get() << '
    '
    ; std::cout << "bar: " << *bar << " " << bar.get() << '
    '
    ; foo.swap(bar); std::cout << "foo: " << *foo << " " << foo.get() << '
    '
    ; std::cout << "bar: " << *bar << " " << bar.get() << '
    '
    ; return 0; }
    を破壊することなく出力する:
    foo: 10 0x2cd9ae0
    bar: 20 0x2cd9b00
    foo: 20 0x2cd9b00
    bar: 10 0x2cd9ae0
    
  • .
    まとめ
  • shared_ptrアドレス空間は複数のスマートポインタで共有することができず、実際の現在のオブジェクトアドレスの役割ドメインが終了すると、変更対象が占有するアドレス空間は
  • から解放される.
  • releaseメンバー関数を使用してunique_を転送ptr隊形のすべての輪、間もなくunique_ptrオブジェクトをunique以外に変換ptrオブジェクトは、アドレス
  • を破壊しない
  • resetを使用すると、オブジェクトアドレス空間がリセットされ、再割り当てされます.アドレス空間
  • を破壊する
  • は、付与メタ演算子を用いる、reset関数と同様にアドレス空間を再指定し、同様にアドレス空間
  • を破壊する.
  • unique_ptrオブジェクトの戻りインテリジェント使用メンバー関数get