スマートポインタは不要になったメモリ領域を自動的に解放するクラスライブラリのこと。
ポインタと同じように扱うことができます。
用途によって使い分ける必要があります。
####std::unique_ptr、boost::scoped_ptr、std::auto_ptr
RAII(資源確保は初期設定)テクニックをサポートするテンプレートクラス。
デストラクタでメモリを解放します。
#include <memory>
{
std::unique_ptr<TStringList> pList(new TStringList());
pList->LoadFromFile("DATA.TXT");
…
} //スコープを外れたところで暗黙のうちにメモリを解放
メモリの解放は「delete ポインタ」で行うため、配列には使用できません。
配列を使うときは次に説明するboost::scoped_arrayを使用します。
#std::unique_ptrは配列を使用できます。
std::auto_ptrはC++0xから非推奨となりました。代わりにstd::unique_ptrを使用します。
なお、std::unique_ptrとstd::auto_ptrとboost::scoped_ptrでは、所有権の移転に違いがあります。
####boost::scoped_array
上のstd::auto_ptr・boost::scoped_ptrは配列には使用できませんでした。
boost::scoped_arrayは配列を扱うときに使用します。
#include <boost/scoped_array.hpp>
{
boost::scoped_array<char> ptr(new char[1000]);
…
} //スコープを外れたところで暗黙のうちにメモリを解放
####boost::shared_ptr
参照カウンタを使ったスマートポインタ。
配列を扱うときは、次のboost::shared_arrayを使用します。
#include <boost/shared_ptr.hpp>
{
boost::shared_ptr<TStringList> list1(new TStringList());
{
boost::shared_ptr<TStringList> list2(new TStringList());
list1 = list2;
}
}
std::vectorなどのコンテナの要素に使用できます。
#include <vector>
#include <boost/shared_ptr.hpp>
{
std::vector<boost::shared_ptr<TCheckBox> > checkboxes;
boost::shared_ptr<TCheckBox>checkbox(new TCheckBox(ScrollBox1));
checkboxes.push_back(checkbox);
}
循環参照が発生すると正しくメモリを解放することができなくなります。
そのような場合はboost::weak_ptrを使用します。
####boost::shared_array
boost::shared_ptrの配列版です。
使い方はboost::shared_ptrと同じです。
#include <boost/shared_array.hpp>
{
boost::shared_array<char> c1(new char[1000]);
{
boost::shared_array<char> c2(new char[2000]);
c1 = c2;
}
}
####boost::weak_ptr
boost::shared_ptrでは、循環参照を上手に扱うことができません。
そのようなときに使用するのがboost::weak_ptrです。
循環参照の一例。
#include <boost/shared_ptr.hpp>
struct Test {
boost::shared_ptr<Test> p;
~Test() { std::puts("~Test"); }
void Say() { std::puts("Hello"); }
};
{
boost::shared_ptr<Test> testA(new Test);
boost::shared_ptr<Test> testB(new Test);
testA->p = testB;
testB->p = testA;
} //解放されない
boost::weak_ptrを使った解決策。
boost::weak_ptrのlock()関数でポインタが有効かどうかをチェックします。
struct Test {
boost::weak_ptr<Test> p; //boost::weak_ptrに変更
~Test() { std::puts("~Test"); }
void Say() { std::puts("Hello"); }
};
boost::shared_ptr<Test> testA(new Test);
{
boost::shared_ptr<Test> testB(new Test);
testA->p = testB;
testB->p = testA;
if (boost::shared_ptr<Test> tmp = testA->p.lock()) {
tmp->Say(); //=> Hello
} //testBを解放
}
//testBは解放済みのためポインタは無効
if (boost::shared_ptr<Test> tmp = testA->p.lock()) {
tmp->Say();
}
####boost::intrusive_ptr
侵入型参照カウント方式。
COMの利用に有効。
サンプルコードは省略。
####おすすめ書籍
Boostの入門書なら『Boost C++ Librariesプログラミング』がお薦め。私も購入しました。