2019.8.20 C++基礎学習ノート——スマートポインタ

4800 ワード

C++基礎学習ノート——スマートポインタ
C++に動的にメモリを割り当てるにはnewとdeleteキーが使用できますが、操作ミスでメモリが漏れることがあるため、C++にスマートポインタが開発されています.スマートポインタの特徴は、使用後に自分でメモリを解放し、メモリ漏洩の問題を避けることです.
スマートポインタauto_ptr
auto_ptrはC++98で提案されたスマートポインタ概念であり,その本質はテンプレートクラスであり,主に動的割り当てによるメモリ漏洩の問題を解決するために用いられる.auto_ptrがメモリ漏洩を解決する方法は、クラスの構造と構造関数、auto_を使用することです.ptrの本質はテンプレートクラスであり、メモリを割り当てるときに構造関数を呼び出し、ポインタの使用が完了した後に構造関数を呼び出してリソースを解放し、メモリの漏洩を避ける目的を達成する.auto_ptrはスマートポインタとして大きな欠陥を有し,主にauto_ptrが値を割り当てると、左のオペランドが指すオブジェクトが自動的に削除されます.例:
auto_ptr ap1(new int(1024));  
auto_ptr ap2;
ap2=ap1;
// ap1   ap2 ,   ap2      ;ap2    ap1     ;ap1      。

そしてauto_ptrは他にも欠陥があるので、C++11ではauto_は使用されません.ptr、shared_の使用に変更ptrとunique_ptr. auto_ptr欠陥分析
スマートポインタshared_ptrとunique_ptr
Shared_ptr/unique_ptrとauto_ptrの最大の違いはshared_ptrはポインタ間でオブジェクトの所有権を共有する問題、すなわちauto_を解決した.ptrの付与値の奇妙な問題.だから容器の要求を満たして、容器の中で使用することができます.そしてauto_ptrは明らかに共有オブジェクトの所有権を禁止し、コンテナでは使用できません.
スマートポインタを使用するヘッダファイルはです.shared_ptrとunique_ptrをスマートポインタとして使用する場合は通常のポインタと変わらずauto_ptrも何の違いもありません.クラス内の構造と構造関数を呼び出してメモリの割り当てと解放を実現します.unique_ptrはアップグレード版のauto_と見なすことができるptr,shared_ptrは、同じオブジェクトを指す複数のスマートポインタをサポートし、shared_ptrクラスでは、スマートポインタが指すオブジェクトが同時に指すスマートポインタの数を専門に記録するメンバーがいます.
//shared_ptr    
template
class shared_ptr
{
private:
       T *px; // contained pointer
    unsignedlong* pn; // reference counter
}

クラス内のメンバーpxはポインタを表し、pnは被指オブジェクトが同時に対応するスマートポインタの個数を表し、pnが0の場合、スマートポインタがオブジェクトを指していないことを表し、メモリが解放される.実はshared_ptrの原理は,pxを用いてポインタを記録し,pnを用いてpxが指すオブジェクトの所有者share_を記録することである.ptrの数、shared_ptrオブジェクトがアクティブドメインに達すると、リソースは解放されず、pnが0になるとポインタが指すリソースが解放されます.
shared_ptr定義規則
shared_ptrは本質的に標準ポインタではなくクラスであるため、直接値を割り当てることも、標準ポインタを使用して値を割り当てることもできず、スマートポインタでスマートポインタに値を割り当てるしかありません.
 int* a=new int(2);
 shared_ptrsp=a;//           
 sp=a;//           

 int* a=new int(2);
 shared_ptr sp(a);//                a     
 shared_ptr sp1(sp);//                      sp1  
 sp1=sp;//              

shared_ptr機能関数
Reset()関数:関数reset()関数をリセットして、スマートポインタが指すオブジェクトをリセットします.reset()関数にパラメータがない場合、スマートポインタは空のポインタにリセットされ、出力指向値は0になります.
//reset()  
int* a=new int(2);
int* b=new int(3);
shared_ptr sp2(a);
shared_ptr sp1(a);
shared_ptr sp(a);
sp.reset(b);//   b      sp
sp.reset(sp2); //     sp2      sp
sp.reset();//           

spにbの所有権を獲得させる.aの所有権を失う.これはaの所有者を少なくすることに注意する.aの所有者が0になると、aのリソースが解放されます.
Swap()関数:交換関数swap()関数は、2つのスマートポインタのメンバーを交換するために使用され、swap()操作を行うと、スマートポインタsp 1とsp 2のpxとpnが交換されます.つまり、ポインタがオブジェクトを指すだけでなく、オブジェクトがポインタ数を同時に共有することもできます.
//swap()  
int* a=new int(2);
shared_ptr sp(a);
shared_ptr sp1(a);
sp.swap(sp1);

Get()関数:px、すなわちオブジェクトポインタを返します.
Use_count関数:*pnを返します.オブジェクトの所有者の数です.
Unique関数:命令*pn=1;オブジェクトの所有者数を1にし、bool数を返します.
shared_ptrインテリジェントポインタには演算子,"=="と"!="が再ロードされています.スマートポインタがオブジェクトに同じかどうかを示すほか、''3つのシンボルが再ロードされます.
shared_ptrスレッドセキュリティ
shared_ptr自体は100%スレッドでは安全ではありません.参照カウント自体は安全でロックされていませんが、shared_ptrには2つのデータメンバーがあり,読み書き操作は原子化できない.ドキュメントによるshared_ptrのスレッドセキュリティレベルは、組み込みタイプ、標準ライブラリコンテナ、stringと同様、すなわちshared_ptrエンティティは、複数のスレッドによって同時に読み取ることができる.2つのshared_ptrエンティティは、2つのスレッドによって同時に書き込むことができ、「プロファイル」は書き込み操作を計算する.複数のスレッドから同じshared_を読み書きする場合ptrオブジェクトでは、ロックが必要です.P.S.ここではこの2,3日見たばかりのスレッド反発ロックpthreadを使用する可能性があります.mutex_lock
shared_ptrポインタ定義削除器
定義shared_ptrインテリジェントポインタの場合、削除器、すなわちオブジェクト参照数が0の場合に呼び出される関数を表すパラメータを追加する方法もあります.定義時に削除器付きパラメータで定義されたスマートポインタは、pn=0、すなわちオブジェクトに対応するポインタがない場合にクラス内構造関数を呼び出してリソースを解放するのではなく、削除器関数を呼び出す.pn=0のときに構造関数を解析してメモリを解放したくない場合は、削除器付きのポインタのみを定義し、pn=0のときに自分で設定した削除器関数操作を自動的に呼び出すことができます.
//           (  )
template shared_ptr(Y * p, D d);
template void reset(Y * p, D d);

//       
void foo(int * d)
{
       cout< sp(a,foo);//      foo     sp
       shared_ptr sp1(sp);
       sp.reset();
       sp1.reset();
       //  a     0 ,                foo,  1234
       system("pause");
       return 0;
}

削除器を使用するときは、次の点に注意してください.
  • 指定された削除器のパラメータはint*でなければならない.とshared_ptrのint対応.他のものではないか、空でも間違っています.システムがsharedをptrのオブジェクトpxは削除器のパラメータに割り当てられ、削除器からリソースを解放することもできます.
  • は、aの参照回数が0の場合にのみ呼び出されるため、sp 1がない.reset().foo関数も呼び出されません.

  • P.S.はshared_を使用していますptrスマートポインタの場合、初期化を定義する際に注意してください.
    int* a=new int(2);
    shared_ptr sp(a);//----------(1)
    shared_ptr sp1(a);//---------(2)
    

    ここの(2)も間違っています.考えてみろptrの構造関数,(1)の場合,spのpxはaを指し,pnは1である.(2)の場合、pxはaを指し、pnも1である.これは明らかに問題だ.aは2回引用するが*pnは1である.最後の役割ドメインが到達すると、メモリが2回解放され、異常が発生します.shared_ptrインテリジェントポインタまとめ