自動的にメモリ領域の開放を行うスマートポインタ

スマートポインタは不要になったメモリ領域を自動的に解放するクラスライブラリのこと。
ポインタと同じように扱うことができます。

用途によって使い分ける必要があります。

####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プログラミング』がお薦め。私も購入しました。

楽天で購入

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください