世の中には様々なスマートポインタが存在しますが
Boostライブラリの中でも,いくつかのスマートポインタが用意されています.
その中でも最も汎用性の有る(気がする)shared_ptrの紹介です.
これは,STLのauto_ptrに参照カウンタを追加したような物で
ポインタを参照する変数の数を覚えておき,0になった時に自動でdeleteを呼んでくれます.
あちこちにポインタをコピーすると,deleteのタイミングを考えるのが大変ですが
shared_ptrはこの辺を自動でやってくれます.
C++で最も多いバグの一つ,「delete忘れ」から来るメモリリーク対策*1に大変有効です.

使い方

格納したいポインタをshared_ptrのコンストラクタの引数にして渡しましょう.

boost::shared_ptr<int> pInt(new int);

な感じです.
このポインタは代入操作で自由にコピーが出来ます.
コピーをすると参照カウンタが+1されます.
また,STLのauto_ptrと違い参照が0になるまでdeleteされないので
コンテナに渡す事もできます.

サンプルプログラム

#include <boost/shared_ptr.hpp>
#include <string>
#include <iostream>
#include <vector>

using namespace std;
struct Object
{
    string str;
    
    Object(const string& InitStr)
    {
        str=InitStr;
    }

    /** デストラクタ
        デストラクタが呼ばれた事を表すメッセージを表示
     */
    ~Object()
    {
        cout << "call "<< str <<"::~Object():" << endl;
    }
};
//毎回打つには長いのでtypedef
typedef boost::shared_ptr<Object> obj_ptr;

int main(int argc, char *argv[])
{    
    if(1)
    {    //ブロック1
        obj_ptr Array[]={
            obj_ptr(new Object("Obj0")),
            obj_ptr(new Object("Obj1")),
            obj_ptr(new Object("Obj2")) };
        if(1)
        {
            //ブロック2
            vector<obj_ptr> v;
            v.insert(v.begin(), Array, Array+3);

            //ブロック2から抜ける(vectorが破棄される)
            cout << "break Block2" << endl;
        }

        //ブロック1から抜ける(配列が破棄される)
        cout << "break Block1" << endl;
    }
    cout << "return" << endl;
    return 0;
}

実行結果

break Block2
break Block1
call ~Object()
call ~Object()
call ~Object()
return

このプログラムでは,shared_ptrを最初のブロック1の中で配列に入れています.
一つ深いブロック2の中で,ポインタをvectorにコピーしています*2
ブロック2を抜ける時にvectorは破棄されるので,その中のポインタも破棄され
参照カウンタが1減り,2から1になります.
ブロック1を抜けた時に,配列も破棄され参照カウンタが0になるので
このタイミングでdeleteが暗黙的に呼ばれます.

メソッド

メソッドの一部を紹介

get(生のポインタを得る)

T * get() const;

shared_ptrの持っている生のポインタを返します.

use_count(参照数を得る);

long use_count() const;

所有権を共有しているshared_ptrオブジェクトの数を得ます.

参照

  • C++ Boost Boost公式ドキュメントの和訳

コメント


お名前:

*1 その逆にも
*2 この時参照カウンタが2になります