shared_ptrスマートポインタの簡単な実現
3544 ワード
shared_ptrはスマートポインタのデータ構造で、スマートポインタの基本機能である自動管理リソースのリリース以外に、もう一つの特徴は「share」です.いわゆる「share」は複数のshared_であると理解しています.ptrは同じ資源を共有し、資源のコピーを避けた.例えば、コピーコンストラクタの操作を行う場合:
px 2またはpx 1が破壊された時に何が発生しますか?それを指す内部資源は同時に廃棄されますか?できません.今の資源はみんなで共有しているので、勝手に廃棄されてはいけません.shared_ptrは、リソースの指向と廃棄を制御するために参照カウントを採用する.内部資源はカウント値countを伴っています.countはshared_がいくつあるかを表しています.ptrはこのリソースを指しています.新しいshared uがあるたびに.ptrがリソースを指す場合、count値に1を加算し、そのリソースを指すshared_ptr破壊時、count値は1を減らし、countが0になった時、その資源を指すすべてのsharred_を証明します.ptrはすでに廃棄されました.この時、内部資源も破壊されます.
自分で簡単なshared_を書きました.ptrテンプレートクラスは、以下の通りです.
構文関数では次のような文が見られます.
テスト手順は以下の通りです.
X(10)constructed.X(20)constructed.X(10):print().X(20):print().X(20)destructed.X(10):print():X(10):print(10):print).X(10)destructed.
参照することができますが、演算子関数を実行した後、shared_px 2が指す内部資源は破壊され、X(20)が分析されているからです.その後shard_px 2とshared_px 1は同じ内部資源を指しています.全部X(10)を印刷しました.プログラムが終了すると、内部資源は全部自動的に破壊されます.
class X{...};
shared_ptr<X> px1(new X());
shared_ptr<X> px2(px1);
または値付け操作時:class X{...};
shared_ptr<X> px1(new X(...));
shared_ptr<X> px2(new X(...));
px2 = px1;
shared_ptrは資源のコピーではなく、内部のポインタを資源に向けるだけでいいです.以上の例では、px 2は、px 1からリソースをコピーするのではなく、内部ポインタをpx 1のリソースに向ける.px 2またはpx 1が破壊された時に何が発生しますか?それを指す内部資源は同時に廃棄されますか?できません.今の資源はみんなで共有しているので、勝手に廃棄されてはいけません.shared_ptrは、リソースの指向と廃棄を制御するために参照カウントを採用する.内部資源はカウント値countを伴っています.countはshared_がいくつあるかを表しています.ptrはこのリソースを指しています.新しいshared uがあるたびに.ptrがリソースを指す場合、count値に1を加算し、そのリソースを指すshared_ptr破壊時、count値は1を減らし、countが0になった時、その資源を指すすべてのsharred_を証明します.ptrはすでに廃棄されました.この時、内部資源も破壊されます.
自分で簡単なshared_を書きました.ptrテンプレートクラスは、以下の通りです.
template<class T>
class my_shared_ptr{
public:
my_shared_ptr(T* pt){
_pBlock = new ControlBlock(pt);
}
my_shared_ptr(const my_shared_ptr& rhs){
_pBlock = rhs._pBlock;
_pBlock->ref_count++;
}
~my_shared_ptr(){
_pBlock->ref_count --;
if(0 == _pBlock->ref_count)
delete _pBlock;
}
my_shared_ptr& operator=(const my_shared_ptr& rhs){
if(this == &rhs)
return *this;
_pBlock->ref_count --;
if(0 == _pBlock->ref_count)
delete _pBlock;
_pBlock = rhs._pBlock;
_pBlock->ref_count++;
}
T* get(){return _pBlock->_ptr;}
T* operator->(){return _pBlock->_ptr;}
void reset(T* pt){
_pBlock->ref_count --;
if(0 == _pBlock->ref_count)
delete _pBlock;
_pBlock = new ControlBlock(pt);
}
private:
struct ControlBlock{
int ref_count;
T* _ptr;
ControlBlock(T* pt){
_ptr = pt;
ref_count = 1;
}
~ControlBlock(){
delete _ptr;
}
};
ControlBlock* _pBlock;
};
my_shared_ptr内部には内部資源を管理するControl Blockがあり、同時にカウント値ref_がある.countマークはその内部資源のmy_を指しています.shared_ptr個数コピーコンストラクタと赋値演算子には、すべてあります._pBlock = rhs._pBlock;
_pBlock->ref_count++;
この二つの文はmy_が発生したときを表します.shared_ptrのコピーは、内部資源をコピーするのではなく、内部ポインタを同じ内部資源に向けてカウント値を増加します.構文関数では次のような文が見られます.
_pBlock->ref_count --;
if(0 == _pBlock->ref_count)
delete _pBlock;
内部資源は勝手に廃棄するのではなく、コンストラクタは計算値を減らし、計算値が0になると内部資源は破壊されるという意味です.オペレータの割り当て関数では、まず自己検査を行い、その次に自身が指す内部リソースを解放し、その後に新しい内部リソースを指し、カウント値を更新する.テスト手順は以下の通りです.
#include "my_shared_ptr.h"
#include <iostream>
using namespace std;
class X{
public:
X(int i):_val(i){
cout << "X(" << _val << ") constructed." << endl;
}
~X(){
cout << "X(" << _val << ") destructed." << endl;
}
void print(){
cout << "X(" << _val << ")::print()." << endl;
}
private:
int _val;
};
int main(){
my_shared_ptr<X> shared_px1(new X(10));
my_shared_ptr<X> shared_px2(new X(20));
shared_px1->print();
shared_px2->print();
shared_px2 = shared_px1;
shared_px1->print();
shared_px2->print();
}
実行結果は以下の通りです.X(10)constructed.X(20)constructed.X(10):print().X(20):print().X(20)destructed.X(10):print():X(10):print(10):print).X(10)destructed.
参照することができますが、演算子関数を実行した後、shared_px 2が指す内部資源は破壊され、X(20)が分析されているからです.その後shard_px 2とshared_px 1は同じ内部資源を指しています.全部X(10)を印刷しました.プログラムが終了すると、内部資源は全部自動的に破壊されます.