参照カウント
1.問題
カウンターはどこに保管されていますか?クラスオブジェクトのメンバーとして、コピー構築をどのように処理しますか?
Hasptr p1("Hiya");
Hasptr p2(p1);
Hasptr p3(p1); //p1,p2,p3指向相同的string
2.解決策
各クラスオブジェクトには参照カウントがあり、すべてのクラスオブジェクトの参照カウントは一意の同期を保証します。
class Hasptr
{
public:
//2. 当创建一个对象时,只有一个对象共享状态,将此计数器初始化为1。
Hasptr(const std::string &s = std::string()):
ps(new std::string(s),
i(0),
use(new std::size_t(1))) {
}
//3. 拷贝构造函数递增共享的计数器,指出给定对象的状态又被一个新的用户所共享。
Hasptr(const Hasptr &p):ps(p.ps),i(p.i),use(p.use){
++*use};
Hasptr& operator=(const Hasptr&);
~Hasptr();
private:
std::string *ps;
int i;
std::size_t *use;//1. 增加一个引用计数,用来记录有多少对象与正在创建的对象共享状态。
}
2.1デストラクタ
デストラクタはカウンタをデクリメントし、状態を共有しているユーザーが1人少ないことを示します。カウンタが0の場合、デストラクタは状態を解放します。
Hasptr ::~Hasptr()
{
if(--*use == 0){
delete ps;
delete use;
}
}
2.2オーバーロードされた割り当て
コピー代入演算子は、右側のオペランドのカウンターをインクリメントし、左側のオペランドのカウンターをデクリメントします。左側のオペランドのカウンターが0の場合、共有状態のユーザーがいないことを意味し、コピー代入演算子は状態を破棄する必要があります。
Hasptr& Hasptr::operator=(const Hasptr& rhs)
{
++*rhs.use; //递增右侧对象的引用计数
if(--*use == 0) //递减和检测本对象的引用计数
{
delete ps;
delete use;
}
ps = rhs.ps;
i = rhs.i;
use = rhs.use;
return *this;
}
3.結果
HasPtr h("hi mom!");
HasPtr h2 = h; // no new memory is allocated,
// h and h2 share the same underlying string
HasPtr ret;
ret = h; // HasPtr passed by value, so it is copied
cout << ret.i << "," << *ret.ps << endl;
【参照】