2004-09-27

boost::shared_ptr  [by miyachi]

宇宙関連ネタが続いていたのでたまには本業に戻ってプログラミングの話題から。以前boostのanyに関して書いたが、本来boostを使い出したのはこのshared_ptrの為だった。

shared_ptrとはいわゆるスマートポインタの実装の1つです。オブジェクト指向言語であるC++ではポインタ変数にnewを使ってオブジェクトを作成するのですが、deleteを忘れる事もあるし何より面倒だしソースも不要に長くなってしまいます。スマートポインタにnewで生成したオブジェクトへのポインタを格納しておけば参照されなくなった時点で自動的に開放してくれます。これを使わずにおくのは勿体ない!

ちなみにSTLにauto_ptrと言うスマートポインタもあるが、これはポインタをコピーした場合等に問題があるので、boostのshared_ptrの方がお勧め。(とokaさんも言っていた。) 使い方も、

#include <boost/shared_ptr.hpp>
boost::shared_ptr<class> class_ptr( new class(...) );

とするだけ。これだけでdeleteする必要が無くなります。疑り深い人はデバッガでclassのデストラクタにブレークポイントを置いて試してみましょう。ほら?便利でしょ?

更にshared_ptrのお勧めの使い方としては、インターフェイスクラスと実装クラスを分離して、このクラスの生成時にファクトリー関数を使う時にポインタをshared_ptrに格納する方法がある。

// インターフェイスクラス
class Name {
public:
 virtual ~Name() {};
 virtual std::string getName() = 0;
};

// 実装クラス
class NameImpl : public Name {
public:
 NameImpl( const std::string name )
 {
  a_name = name;
 }
 virtual ~NameImpl() {};
 std::string getName()
 {
  return a_name;
 }
private:
 std::string a_name;
};

// ファクトリー関数
boost::shared_ptr<Name> makeName( const std::string &name )
{
 boost::shared_ptr<Name> name_ptr( new NameImpl( name ) );
 return name_ptr;
}

// 使い方
void printName()
{
 std::string myname = "miyachi";
 boost::shared_ptr<Name> name_ptr = makeName( myname );
 std::cout << "Name = " << name_ptr->getName() << std::endl;
}

ヘッダファイルにはインターフェイスクラスとファクトリー関数の定義だけ書かれていれば良い。インターフェイスと実装の分離は他の人に使ってもらうライブラリ等を構築する時には必須であろうと思う。

インターフェイスクラスと実装クラスそれにファクトリー関数等に関してはEffective C++の34項にあるので興味があればチェックして見ましょう。

私もまだ修行中の身ゆえ突っ込み歓迎ですのでコメント下さいm(_ _)m

# 東京は今日は雨がふってます。
# ブレードランナーの曲でもiTunesでかけながら午後のプログラミングを開始!
2004-09-27 12:41:41 - miyachi - - [プログラミング] -