4種類のスマートポインタC++

25866 ワード

インテリジェントポインタの役割は、関数の終了時に申請されたスペースが解放され忘れ、メモリが漏洩するため、ポインタを管理することです.インテリジェントポインタを使用すると、この問題を大幅に回避できます.インテリジェントポインタはクラスであり、クラスの役割ドメインを超えた場合、クラスは自動的に構造関数を呼び出し、構造関数は自動的にリソースを解放します.したがって、スマートポインタの機能原理は、関数の終了時にメモリ領域を自動的に解放し、手動でメモリ領域を解放する必要がないことです.
C++の4つのスマートポインタ:auto_ptr, shared_ptr, weak_ptr, unique_ptr .ここでauto_ptrはc++11によって廃棄された.1.auto_ptrは所有権モードを採用する.コピーと割り当ての過程で、元のオブジェクトに対するメモリの制御権が奪われます.オブジェクトに渡した後、元のオブジェクトポインタをnullptrにします.
auto_ptr< string> p1 (new string ("I reigned lonely as a cloud.));
auto_ptr<string> p2;
p2 = p1; //auto_ptr    .

この場合、p 2はp 1の所有権を剥奪することはないが、プログラムが実行されるとp 1にアクセスするとエラーが発生する.だからauto_ptrの欠点は、潜在的なメモリクラッシュの問題があることです.
2. unique_ptr uniqueは専属所有権です.unique_からptrが管理するメモリは、1つのオブジェクトにのみ保持され、レプリケーションと割り当てはサポートされません.所有権モードを採用するか,それとも上記の例では意味のコピーが禁止されており,所有権の移転が必要な場合,std::move()メソッドにより所有権の移転を制御することができる.
	//     
	unique_ptr <int> p1(new int(10));
    cout<<"p1="<<*p1<<endl;
    unique_ptr <int> p2;
    /*
      	p2=p1;//  
    */
    p2=move(p1);
    cout<<"p2="<<*p2<<endl;
	//     
    auto w=std::make_unique<int>(10);//  make_unique  
    cout<<*(w.get())<<endl;//  get()    w     
    /*
        auto w2 = w;//  ,   w   w2。
    */
    auto w2=std::move(w);//      , w       w2,
    //w   nullptr;
    cout<<"w="<<((w.get()!=nullptr)?(*w.get()):-1)<<endl;//-1
    cout<<"w2="<<((w2.get()!=nullptr)?(*w2.get()):-1)<<endl;//10
    w=std::make_unique<int>(20);//    w  ,    
    cout<<*(w.get())<<endl;

3.shared_ptr shared_ptrは共有型所有概念を実現する.複数のスマートポインタは、同じオブジェクトを指します.このオブジェクトとその関連リソースは、最後のリファレンスが破棄されたときに解放されます.カウントを参照するメカニズムには、共有可能なスマートポインタが用意されています.release()を呼び出すと、現在のポインタはリソース所有権を解放し、カウントを1つ減らします.カウントが0に等しい場合、オブジェクトは参照されず、プロファイルでき、リソースが解放されます.
//shared_ptr
{
 //    shared_ptr  ,       .
 //  shared_ptr            
 auto w1=shared_ptr <int>(new int(20));
 {
 	auto w2=w1;//w2,w1       
    cout<<((w1.get()!=nullptr)?(*w1.get()):-1)<<endl;//20
    cout<<((w2.get()!=nullptr)?(*w2.get()):-1)<<endl;//20
    cout<<w1.use_count()<<endl;//use_count          ,2
    cout<<w2.use_count()<<endl;//2
 }
}
//move  ;
auto w3=shared_ptr <int>(new int(30));//
auto w4=move(w3);// w3       w4,  w3 nullptr
cout<<((w3.get()!=nullptr)?(*w3.get()):-1)<<endl;//-1
cout<<((w4.get()!=nullptr)?(*w4.get()):-1)<<endl;//30
//w        ,    0; w4     ,    1
cout<<w3.use_count()<<endl;//0
cout<<w4.use_count()<<endl;//1
return 0;
class b;//  b 
class a
{
public:
    shared_ptr<b> pb;
    ~a() {cout<<"~a()"<<endl;}
};
class b
{
public:
    shared_ptr<a> pa;
    ~b() {cout<<"~b()"<<endl;}
};
//pa pb       ,pa pb       
void fun1()
{
    cout<<"   :"<<endl;
    shared_ptr<a>ta(new a());
    shared_ptr<b>tb(new b());
    cout<<ta.use_count()<<endl;//1
    cout<<tb.use_count()<<endl;//1
    ta->pb=tb;
    tb->pa=ta;
    cout<<ta.use_count()<<endl;//2
    cout<<tb.use_count()<<endl;//2
}

問題:循環参照数が発生すると循環参照の問題が発生し、メモリが正常に回収されず、メモリが漏洩する可能性があります.
4.weak_ptrはshared_を解決するためにptrに存在するループリファレンスの問題はweak_を導入するptr weak_ptrは、shared_を指すオブジェクトのライフサイクルを制御しないスマートポインタです.ptr管理の対象このオブジェクトのメモリ管理を行うのは、その強い参照のshared_です.ptr. weak_ptrは、管理オブジェクトへのアクセス手段を提供するだけです.weak_ptr設計の目的はshared_に合わせることですptrが導入したスマートポインタはshared_を支援するptrは1つのsharedからのみ動作します.ptrまたは別のweak_ptrオブジェクト構造は、参照記数の増加または減少を引き起こさない構造および析出構造である.weak_ptrはshared_を解決するために使用されますptr相互参照時のデッドロック問題、2つのshared_ptrが互いに参照すると、この2つのポインタの参照カウントは永遠に0に下がることができず、リソースは永遠に解放されません.オブジェクトへの弱い参照です.オブジェクトの参照数とshared_は増加しません.ptr間は互いに変換できるshared_ptrは直接値を割り当てることができ、lock関数を呼び出すことでshared_を得ることができる.ptr. weak_ptrアシスタントshared_ptr動作(オブザーバーモードに類似)、weak_ptrはshared_のみptrは参照を行い、その参照個数は変更されません.share_ptrが無効になった後、対応するweak_ptrも失効します.
class bb;//  b 
class aa
{
public:
    shared_ptr<bb> pb1;
    ~aa() {cout<<"~aa()"<<endl;}
};
class bb
{
public:
    weak_ptr<aa> pa1;//     weak_ptr
    ~bb() {cout<<"~bb()"<<endl;}
};
void fun2()
{
    cout<<"   :"<<endl;
    shared_ptr<aa>ta1(new aa());
    shared_ptr<bb>tb1(new bb());
    cout<<ta1.use_count()<<endl; //1
    cout<<tb1.use_count()<<endl; //1
    ta1->pb1=tb1;
    tb1->pa1=ta1;
    cout<<ta1.use_count()<<endl;//1
    cout<<tb1.use_count()<<endl;//2
}