[解決済み] クラスメンバにスマートポインタを使用する
質問
C++11のクラス・メンバーとしてのスマート・ポインタの使い方を理解するのに苦労しています。 スマート・ポインタについて多くの本を読み、どのようにすれば
unique_ptr
と
shared_ptr
/
weak_ptr
は一般的に働きます。わからないのは、実際の使用方法です。誰もが
unique_ptr
を、ほぼ常に使用するようにします。しかし、このようなものをどのように実装すればよいのでしょう。
class Device {
};
class Settings {
Device *device;
public:
Settings(Device *device) {
this->device = device;
}
Device *getDevice() {
return device;
}
};
int main() {
Device *device = new Device();
Settings settings(device);
// ...
Device *myDevice = settings.getDevice();
// do something with myDevice...
}
例えば、ポインターをスマートポインターに置き換えるとします。A
unique_ptr
のため、うまくいきません。
getDevice()
ということですよね?だから、そういう時にこそ
shared_ptr
と
weak_ptr
? を使用する方法はありません。
unique_ptr
? ほとんどの場合
shared_ptr
の方が、よほど小さなスコープでポインタを使うのでない限り、理にかなっているのではないでしょうか?
class Device {
};
class Settings {
std::shared_ptr<Device> device;
public:
Settings(std::shared_ptr<Device> device) {
this->device = device;
}
std::weak_ptr<Device> getDevice() {
return device;
}
};
int main() {
std::shared_ptr<Device> device(new Device());
Settings settings(device);
// ...
std::weak_ptr<Device> myDevice = settings.getDevice();
// do something with myDevice...
}
ということでいいのでしょうか?ありがとうございました。
どのように解決するのですか?
<ブロッククオート
A
unique_ptr
のために動作しません。
getDevice()
ということですね?
いいえ、必ずしもそうではありません。ここで重要なのは、適切な
オーナーシップポリシー
を使用します。
Device
オブジェクトの所有者、つまり (スマート) ポインタが指すオブジェクトの所有者になるのは誰かということです。
のインスタンスになるのでしょうか?
Settings
オブジェクト
単独
? を使用するのでしょうか?
Device
オブジェクトは自動的に破棄されなければなりません。
Settings
それとも、そのオブジェクトよりも長持ちさせるべきでしょうか?
最初の場合
std::unique_ptr
が必要です。
Settings
は、指されたオブジェクトの唯一の(ユニークな)所有者であり、その破壊に責任を持つ唯一のオブジェクトです。
この前提で
getDevice()
は、単純な
観測中
ポインタ(観察ポインタとは、指されたオブジェクトを生かさないポインタのことです)。最も単純な観測ポインタは生ポインタである。
#include <memory>
class Device {
};
class Settings {
std::unique_ptr<Device> device;
public:
Settings(std::unique_ptr<Device> d) {
device = std::move(d);
}
Device* getDevice() {
return device.get();
}
};
int main() {
std::unique_ptr<Device> device(new Device());
Settings settings(std::move(device));
// ...
Device *myDevice = settings.getDevice();
// do something with myDevice...
}
[
注1.
なぜ私がここで生のポインタを使うのか、不思議に思われるかも知れません。実際、これは貴重な警告なのですが、正しい文脈に置くことが重要です。
手動でのメモリ管理に使用する場合
を使ったオブジェクトの割り当てや解放などです。
new
と
delete
. 純粋に参照セマンティクスを実現し、非所有で観察中のポインタを受け渡す手段として使う場合、ぶら下がったポインタを参照解除しないように注意しなければならないという事実を除けば、生のポインタに本質的に危険なものはありません。
-
注1を終了します。
]
[
注2.
コメントで出てきたように、所有権が一意であるこの特殊なケースで
そして
の場合、所有するオブジェクトは常に存在することが保証されています(つまり、内部データ・メンバである
device
は決して
nullptr
), 関数
getDevice()
はポインタではなく、参照を返すことができる(そしておそらくそうすべき)。これは正しいのですが、私はここで生のポインタを返すことにしました。
device
は
nullptr
また、手動でのメモリ管理に使用しない限り、生ポインタは問題ないことを示すためです。
-
ノート2を終了する
]
もちろん、もしあなたが
Settings
オブジェクトは
ではなく
は、デバイスの排他的所有権を持つ。このようなケースは例えば
Settings
オブジェクトの破壊を意味するものではありません。
Device
オブジェクトも同様です。
これは、プログラムの設計者であるあなたにしかわからないことです。あなたの提供する例からは、そうであるかどうか私にはわかりません。
それを理解するために、「他のオブジェクトは?
Settings
を保持する権利を有するもの。
Device
オブジェクトへのポインタを保持する限り、受動的なオブザーバーではなく、生き続けることができるのです。もし本当にそうであるなら、そのためには
共有オーナーシップポリシー
というものである。
std::shared_ptr
を提供しています。
#include <memory>
class Device {
};
class Settings {
std::shared_ptr<Device> device;
public:
Settings(std::shared_ptr<Device> const& d) {
device = d;
}
std::shared_ptr<Device> getDevice() {
return device;
}
};
int main() {
std::shared_ptr<Device> device = std::make_shared<Device>();
Settings settings(device);
// ...
std::shared_ptr<Device> myDevice = settings.getDevice();
// do something with myDevice...
}
注目すべきは
weak_ptr
は
を観察する
言い換えれば、指されたオブジェクトに対する他のすべての所有ポインタがスコープ外に出た場合、指されたオブジェクトを生かし続けることはできません。
の利点は
weak_ptr
は、通常の生ポインタよりも、安全に
weak_ptr
は
ぶらさがり
を指しているかどうか (すなわち、有効なオブジェクトを指しているかどうか、 元々指していたオブジェクトが破棄されているかどうか)。これを行うには
expired()
メンバ関数は
weak_ptr
オブジェクトを作成します。
関連
-
[解決済み】構造体のベクター初期化について
-
[解決済み】IntelliSense:オブジェクトに、メンバー関数と互換性のない型修飾子がある
-
[解決済み】C++エラー:の初期化に一致するコンストラクタがありません。
-
[解決済み] 非常に基本的なC++プログラムの問題 - バイナリ式への無効なオペランド
-
[解決済み】エラー:strcpyがこのスコープで宣言されていない
-
[解決済み】CMakeエラー at CMakeLists.txt:30 (project)。CMAKE_C_COMPILER が見つかりませんでした。
-
[解決済み] 警告:暗黙の定数変換でのオーバーフロー
-
[解決済み] using namespace std;」はなぜバッドプラクティスだと言われるのですか?
-
[解決済み] スマートポインターとは何ですか?
-
[解決済み】どのような時にどのようなポインタを使えばいいのでしょうか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】構造体のベクター初期化について
-
[解決済み】C++ クラスヘッダが含まれているときに「不明な型」があるのはなぜですか?重複
-
[解決済み】非静的メンバ関数への参照を呼び出す必要がある
-
[解決済み】Visual C++で "Debug Assertion failed "の原因となる行を見つける。
-
[解決済み】CMakeエラー at CMakeLists.txt:30 (project)。CMAKE_C_COMPILER が見つかりませんでした。
-
[解決済み] 解決済み] `pthread_create' への未定義の参照 [重複] [重複
-
[解決済み] gdbを使用してもデバッグシンボルが見つからない
-
[解決済み] to_string は std のメンバーではない、と g++ が言っている (mingw)
-
[解決済み】警告 - 符号付き整数式と符号なし整数式の比較
-
[解決済み] スタックアロケーションにより初期化されていない値が作成された