C++11 スマートポインタ について

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
roxas710
記事: 54
登録日時: 11年前

C++11 スマートポインタ について

#1

投稿記事 by roxas710 » 8年前

C++とDirectXでゲームを開発していまして、生のポインタを扱うと危険なのが分かって、
スマートポインタを勉強中で直している最中なのですが困ったことがあります。


今現在のソースが、

コード:

A* a;
a = new A;
A->Init();
A->Collision();

delete A;
こんな感じのソースを
これに直しました。

コード:

unique_ptr<A> a;
a = make_unique<A>();
a->Init();
a->Collision();
ここで困ったのですが、

コード:

Collision(A,B); 
みたいに関数に値を渡す際に、ユニークポインタを使っているとうまく値を
渡すことができません。
スマートポインタを使わずに一番上の例みたいに生のポインタだと
上手くいくのですが、スマートポインタを使い関数に値を渡す方法が分からないので教えてください。

Egg

Re: C++11 スマートポインタ について

#2

投稿記事 by Egg » 8年前

unique_ptr::getを使用してください。
複数のオブジェクトで共有される可能性のあるポインタ(例えば、リソースなど)には
shared_ptrを用いてください。

roxas710
記事: 54
登録日時: 11年前

Re: C++11 スマートポインタ について

#3

投稿記事 by roxas710 » 8年前

やりたいことが出来ました!!!ありがとうございます。
unique_ptrとshared_ptrとweek_ptrの使い分けで主に
どういった感じで使い分かればいいのでしょうか?
参考にしていたサイトがunique_ptrを使っていたので、
全部unique_ptrにしていたのですが。。。

アバター
milfeulle
記事: 47
登録日時: 11年前
住所: マリーランド
連絡を取る:

Re: C++11 スマートポインタ について

#4

投稿記事 by milfeulle » 8年前

std::unique_ptr<T>は、このスマートポインタがただ1つのデータを指していることを保証するために、このインスタンス自体をコピーできないようになっています。所有権を持つといいます。

コード:

std::unique_ptr<int> sp = std::make_unique<int>(0);
std::unique_ptr<int> another_sp = sp; // error!
ただし、所有権はほかのスマートポインタに移動できます。所有権を移動するためには、右辺値にキャスト、専用のヘルパー関数を使えばmoveすることで実現します。

コード:

std::unique_ptr<int> sp = std::make_unique<int>(0);
std::unique_ptr<int> another_sp = std::move(sp); // move
このばあい、もとの「sp」は内部のポインタがnullptrになって使えなくなっています。(これが従来のconst左辺値参照だと、spがconstで変更できないのですが、右辺値参照だと変更できるので実現できます。)
つまり、「spを捨てて、another_spに移動」します。

もしもある関数void func(int*)があったとして、ポインタを渡すときは、
「(同じスレッドで)その関数がそのポインタを別のどこかに記録などして使い回さない」と分かっているときはsp.get()などとしてポインタを渡しても大丈夫です。
そうでないならshared_ptrを渡します。

unique_ptrが普通のポインタと同等に高速ですが、shared_ptrはリファレンスカウンタも余分に確保する分、遅くなっています。
複数のクラスでデータを共有せざるを得ない場合、shared_ptrを使い、そうでないならunique_ptrを使いましょう。weak_ptrはshared_ptrを使ったときに必要になるケースがあります。
(参考 : http://qiita.com/MasayaMizuhara/items/0 ... aa6d17bb66

優先順位としてはこうでしょう :
1. そもそもnewしない。 (A a)
2. 何らかのコンテナを使う。 (std::vector<A> a_list)
3. std::unique_ptrを使う。
4. std::shared_ptr/std::weak_ptrを使う。
5. Aを管理するクラスを作って1~4を使う。(class AManager { ... [中にstd::vector<A>, std::unqiue_ptrなど] ... }
6. Aを管理するクラスを作る。(newを使用。ただしコンストラクタでnewしてデストラクタでdeleteすることを守る。)

ちなみに、1つだけのインスタンスが作られると分かっていて、コンストラクタでインスタンスを生成するのが遅くなるという場合 :

コード:

class C {
public:
	C() : a { } {

	}
	void create() {
		// ここでaを作りたい
	}
private:
	A a;
};
は、Optional (次期C++に入る予定。他にもいろいろ実装されているので参考に自分で作っても良いでしょう。)を使うといいです。
std::optional<A> a;
とメンバに持ち、初期化が必要になったときに
a.emplace( なんとか )
とすれば、ヒープからメモリを確保せずに初期化できて便利です。
ζ*'ヮ')ζプログラミングはみんなで奏でるシンフォニー

閉鎖

“C言語何でも質問掲示板” へ戻る