C ++入門書の5番目のメモ(第12章動的メモリ)shared_ptr

1.関連する概念

1.1使用シナリオ

•プログラムは、使用する必要のあるオブジェクトの数を認識していません•プログラムは、必要
なオブジェクトの正確なタイプを認識していません•プログラムは
、複数のオブジェクト間でデータを共有する必要があります

1.2実装の原則

  • shared_ptrオブジェクトには、通常は参照カウントと呼ばれるカウンターが関連付けられています。
  • 一部の操作では、カウンターがインクリメントされ、
    shared_ptrがコピーされます。たとえば、shared_ptrは、別のshared_ptrを(関数パラメーターとして、関数の戻り値として)初期化します。
  • 一部の操作カウンターはデクリメントし、
    shared_ptrに新しい値を割り当てます。shared_ptrが破棄されると
  • shared_ptrのカウンターが0になると、管理しているオブジェクトを自動的に解放します。

2.主な操作

オペレーティング 説明
make_shared(args) タイプTの動的に割り当てられたオブジェクトを指すshared_ptrを返します。このオブジェクトをargsで初期化します
shared_ptr p(q) pはshared_ptrqのコピーです。この操作は、qのカウンターをインクリメントします。qのスマートポインタは* Tに変換する必要があります
p = q pとqは両方ともshared_ptrであり、保存されるポインターは相互に変換可能でなければなりません。この操作により、pの参照カウントがデクリメントされ、qの参照カウントがインクリメントされます。pの参照カウントが0になると、それによって管理されていた元のメモリが解放されます。
p.unique() p.use_count()が1の場合はtrueを返し、そうでない場合はfalseを返します。
p.use_count() pと共有されているスマートポインタの数を返します。主にデバッグのために遅くなる可能性があります

2.1定義

例えば。

shared_ptr<string> p1; //shared_ptr,可以指向string 
shared_ptr<list<int>> p2; //shared_ptr,可以指向int的list

//使用make_shared函数
shared_ptr<int> p3 = make_shared<int>(42); 
shared_ptr<string> p4 = make_shared<string>(10, '9'); 
shared_ptr<int> p5 = make_shared<int>();
auto p6 = make_shared<vector<string>>();

 shared_ptr<string>sp;
 make_shared<string>();   //动态分配内存默认初始化,必须要有括号, 默认初始化得到的是空指针
 make_shared<string>("a");      //动态分配内存值初始化
 shared_ptr<string>sp2 = make_shared<string>();   //初始化智能指针
 shared_ptr<string>sp3 = make_shared<string>("b");//初始化智能指针

//和new结合
shared_ptr<int> p1=new int(1024); //error
shared_ptr<int> p2(new int(1024)); //ok, 直接初始化形式。

2.2コピーと割り当て

auto r = make_shared<int>(42); // r指向的int只有一个引用者
r = q;  
// r指向了q所指向的地址
// 递增q所指向对象的引用计数
// 递减r原来所指向对象的引用计数
// r原来所指向对象的引用计数为0,即没有引用者,自动释放

例えば。

//传递参数会构造一个,计数器递增,函数运行结束后释放
shared_ptr<string> fun1(shared_ptr<string> sp5)
{
    
    
    auto sp6 = sp5;                            //创建临时并赋值,计数器递增。
    cout << "sp5 use_count:" << sp5.use_count() << endl;
    cout << "sp5 is_unique:" << sp5.unique() << endl;
    return sp6;
}      
                                       
int main()
{
    
    
    shared_ptr<string>sp = make_shared<string>("aa");
    //通常使用auto来简化定义一个对象来保存make_shared的结果,这种方式比较简单。
    auto sp3 = make_shared<string>(10,'a');
    cout << "sp use_count:" << sp.use_count() << endl;
    auto sp2(sp);                          //拷贝sp,count计数会增加
    cout << "sp use_count:" << sp.use_count() << endl;
    cout << "sp is_unique:" << sp.unique() << endl;
    sp2 = sp3;                             //赋值sp2,计数会减少
    cout << "sp use_count:" << sp.use_count() << endl;
    cout << "sp is_unique:" << sp.unique() << endl;
    auto sp4(sp3);
    cout << "sp3 use_count:" << sp3.use_count() << endl;
    cout << "sp3 is_unique:" << sp3.unique() << endl;
    sp = sp3;//sp指向sp3指向的,sp指向的被销毁。
    cout << "sp use_count:" << sp.use_count() << endl;
    cout << "sp is_unique:" << sp.unique() << endl;
    auto sp7 = fun1(sp);                  
    cout << "sp7 use_count:" << sp.use_count() << endl;
    cout << "sp7 is_unique:" << sp.unique() << endl;   
}

出力結果:
ここに画像の説明を挿入

3.その他の定義方法とリセット方法

オペレーティング 説明
shared_ptr p(q) pは、組み込みポインタqが指すオブジェクトを管理します。qは、newによって割り当てられたメモリを指している必要があり、T *タイプに変換できます。
shared_ptr p(u) pはunique_ptruからオブジェクトの所有権を引き継ぎます; uをnullに設定します
shared_ptr p(q、d) pは、組み込みポインターqが指すオブジェクトの所有権を引き継ぎます。qはT *タイプに変換可能でなければなりません。pは、削除の代わりに呼び出し可能オブジェクトdを使用します
shared_ptr p(p2、d) pはshared_ptrp2のコピーですが、唯一の違いは、pがdeleteの代わりに呼び出し可能なオブジェクトdを使用することです。
プリセット() pがそのオブジェクトを指す唯一のshared_ptrである場合、resetはオブジェクトを解放します。
p.reset(q) 元のオブジェクトを解放するときに、オプションの組み込みパラメーターポインターqが渡されると、pはqを指します。それ以外の場合は、nullに設定されます。
p.reset(q、d) パラメータdも渡された場合、削除の代わりにdが呼び出されてqが解放されます。

注:削除の場合に間違いを犯しやすいため、getを使用して別のスマートポインターを初期化したり、スマートポインターに値を割り当てたりしないでください。

        shared_ptr<int>p(new int(42));
        int* q = p.get();
        cout << "count:" << p.use_count() << *q << endl;
       // delete q; //error:
        {
    
    
            auto t = shared_ptr<int>(q); //转换   
            cout << "count:" << t.use_count() << endl;
        }
        int nVal = *p;
        cout << nVal << endl;

		if(!p.unique())
    		p.reset(new string(*p)); //我们不是唯一的用户;分配新的拷贝

		*p+=newVal; //可以改变对象的值

5.カスタム削除機能

 struct destination {
    
    
 };                //正在连接什么
 struct connection {
    
    
};

 class test2 {
    
    
     public:
        connection& connect(connection* s)
       {
    
    
             cout << "正在连接..." << endl;
            s = new connection();
            return *s;
       }

       void static disconnect(connection* s)
       {
    
    
           cout << "正在断开连接..." << endl;
       }

      void test()
      {
    
    
         connection p;
          connection* d = new connection();
          p = connect(d);
        //shared_ptr<connection>sp(&p,disconnect);   
       //error:lambda代表了删除函数。那么参数列表也要和删除函数一致,因为delete内部是free(p)。
       //shared_ptr<connection>sp(&p, [&p] { disconnect(&p); });
         shared_ptr<connection>sp(&p, [](connection* s) {
    
     disconnect(s); });
      } 
 };

おすすめ

転載: blog.csdn.net/thefist11cc/article/details/113914912