スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

【コード】boost::shared_ptr、boost::scoped_ptr

先日我がプロジェクトにようやく boost ライブラリを導入致しました。
色々な機能があり、どんな機能があるのかは全然解りませんが
とりあえずスマートポインタという物を始めて触りました。

使ってみた感想は今のところよく解らないですw
今まで通り扱えるように出来てますので大幅な変更は殆どありませんでした。

そんな訳で少し boost::shared_ptr、boost::scoped_ptr に触れてみましたので
コード付きで色々載せてみます。


使う前にプロジェクトのプロパティより、
「構成プロパティ」→ 「C/C++」→ 「全般」にある
「追加のインクルード ディレクトリ」に boost_lib へのファイルパスを通してあります。


boost::shared_ptr、boost::scoped_ptr を扱うためにはそれぞれ
#include <boost/shared_ptr.hpp>
#include <boost/scoped_ptr.hpp>


をインクルードします。


内部で参照カウンタと呼ばれるものが存在しているそうで、
この参照カウンタが 0 になると自動的に確保した領域を解放してくれるようです。

参照カウンタが 1 以上だとどこかで参照されていると言う事になるので
解放は起こらないという仕組みだそうです。

例えば、色々なクラス内部でポインタを保持したい場合、
スマートポインタを使わない場合は削除するタイミングを常に意識しなければいけません。
勝手に delete なんかしてしまうと即座にアクセスバイオレーションになります。

これを使うと、そう言った煩わしさがなくなるとのことで早速導入しました。
正直個人のプロジェクトですので気を付けていればどうにでもなるんですけどね…


shared と scoped と二つのクラスが用意されてますが、
どう使い分ければいいのでしょうか…。
私自身あんまし把握出来ておりません。


とりあえず、他のオブジェクトからも参照する場合は shared、
他のオブジェクトから参照されない(存在するのは一つの)場合は scoped を使うようにしてます。
(scoped の方がより限定的に扱うスマートポインタと言う認識ですかね。)


実際使う時はこんな感じで記述します。
boost::shared_ptr<型> spShared;
boost::scoped_ptr<型> spScoped;

boost::shared_ptr<型> spShared(new 型());
boost::scoped_ptr<型> spScoped(new 型());


例えば CBase クラスをスマートポインタにしたい場合は、
boost::shared_ptr<CBase> spShared; // インスタンスの生成はしない
boost::scoped_ptr<CBase> spScoped;

boost::shared_ptr<CBase> spShared(new CBase()); // インスタンスも一緒に生成
boost::scoped_ptr<CBase> spScoped(new CBase());

こうなります。


個人的にちょっとややこしく感じたのがアスタリスクで、ポインタを扱うので
boost::shared_ptr<CBase*> spShared;
boost::scoped_ptr<CBase*> spScoped;

アスタリスクが必要なのではないかと思ったのですが必要ないようです。

メンバメソッドにアクセスしたい場合は、
アロー演算子がオーバーロードされておりますので普段通りのポインタのように扱えます。


int main()
{
boost::shared_ptr<CBase> spShared(new CBase());
boost::shared_ptr<CBase> spScoped(new CBase());

spShared->Uhehe();
spScoped->Uhehe("うへへ");

return 0;
}

クラス内でスマートポインタを使う場合は、
コンストラクタの初期化子リストを使用します。

// ベースクラス
class CBase
{
private:
boost::shared_ptr<CBase> spShared;
boost::shared_ptr<CBase> spScoped;

public:
CBase():spShared(new CBase()), spScoped(){ }
virtual ~CBase(){ }
};

shared の方はインスタンスを生成したバージョンです。
scoped の方は生成しないバージョンです。

今保持しているポインタを破棄して新しいポインタを保持したい場合は reset() メソッドを使うようです。
spShared.reset(new CDerived); // CBase へのポインタを破棄して CDerived へのポインタを保持する
spScoped.reset(new CDerived);


shared(scoped)のメンバですので「. 演算子」でアクセスします。
「-> 演算子」を使うと保持しているクラスのメンバメソッドになってしまいます。



先程も言ってたアスタリスクを付けてないのに
ポインタとして扱えているのか?と言う所に疑問が残り多態性についてもテストしました。
結果はばっちりOKでした。


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

// ベースクラス
class CBase
{
public:
CBase()
{
std::cout<< "CBase::Constructor\n";
}

virtual ~CBase()
{
std::cout<< "CBase::Destructor\n";
}

virtual void Print()
{
std::cout<< "CBase::Print\n";
}
};

// 派生クラス
class CDerived : public CBase
{
public:
CDerived()
{
std::cout<< "CDerived::Constructor\n";
}

~CDerived()
{
std::cout<< "CDerived::Destructor\n";
}

virtual void Print()override
{
std::cout<< "CDerived::Print\n";
}
};


int main()
{
boost::shared_ptr<CBase> spShared(new CDerived());
spShared->Print();
return 0;
}



実行結果はこうなりました。
CBase::Constructor
CDerived::Constructor
CDerived::Print
CDerived::Destructor
CBase::Destructor
続行するには何かキーを押してください . . .


派生クラスの Print() メソッドが呼ばれているのでOKですね。
delete をしなくても勝手に解放されるのデストラクタもしっかり呼ばれてます。



最後に、コンテナ(std::list や std::vector)にもスマートポインタが使用出来るので
その方法を記述して記事を終わりたいと思います。

int main()
{

std::list< boost::shared_ptr<CBase> > List;
List.push_back( boost::shared_ptr<CBase>(new CDerived()) );

std::list< boost::shared_ptr<CBase> >::iterator wIt = List.begin();

(*wIt)->Print();

std::cout<< "\nList.erase()\n";
wIt = List.erase(wIt);

std::cout<< "\nProgram ended\n";

return 0;
}


実行結果はこうなります。

CBase::Constructor
CDerived::Constructor
CDerived::Print

List.erase()
CDerived::Destructor
CBase::Destructor

Program ended
続行するには何かキーを押してください . . .


std::list にスマートポインタを使う例です。
今回無駄にイテレータも作成し、そこから Print() メソッドを呼んでおります。
erase() メソッドが呼ばれるとデストラクタが走っております。


一応テストはここで終了です。
色々足りない所も有りますが、今のところ扱うだけならこれで十分かなと思いました。
(必要ならまた調べればいいですし…)

まだまだ boost の初歩の初歩くらいですが楽しいなと思いましたw
こんなに簡単に使えるんならもっと早く使っとけばよかったorz
スポンサーサイト
NEXT≫
検索フォーム
プロフィール

DVDM

Author:DVDM
自作ゲームの開発過程ブログ。
赤髪愛なら誰にも負けない。

 
Pixiv バナー


ブロとも申請フォーム
最新記事
カテゴリ
最新コメント
最新トラックバック
RSSリンクの表示
リンク
ブロとも一覧
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。