私は、enable_shared_from_thisの子クラスであるクラスを持っているとしましょう。この基本クラスのドキュメントでは、shared_from_thisを呼び出す前に、このクラスを所有する共有ポインタが必要であることを示しています。クラスをnewで割り当て、オブジェクトを管理するshared_from_thisを呼び出すことは安全ですか?C++でマネージド共有ポインタなしでshared_from_this()を使用する
答えて
いいえ、安全ではありません。オブジェクトがnew
(関連付けられていないshared_ptr
なし)によって割り当てられていないshared_ptr
で管理されている場合は、shared_from_this
に電話をかけてください。例えば、このコード
struct Test: std::enable_shared_from_this<Test> {
std::shared_ptr<Test> getptr() {
return shared_from_this();
}
};
Test *test = new Test;
std::shared_ptr<Test> test2 = test->getptr();
は(libstdc++
を使用して少なくとも)std::bad_weak_ptr
をスローします。しかし、これはOKです:標準から
std::shared_ptr<Test> test(new Test);
std::shared_ptr<Test> test2 = test->getptr();
:
§20.8.2.4
のshared_ptr shared_from_this();
shared_ptr shared_from_this()const;
7 *が必要です:enable_shared_from_thisが、これは型Tのオブジェクトtの サブオブジェクトが&トンを所有している少なくとも一つのshared_ptrのインスタンスPがなければならないものでなければならないT. のアクセス可能基底クラスでなければなりません。
8戻り値:pと所有権を共有するshared_ptrオブジェクトr。
9事後条件:r.get()==この
あなたはshared_ptr
によって管理されていないクラス内shared_from_this()
を呼び出す場合は、のいずれかを満たしていないため、結果は未定義の動作になります文書化された方法の前提条件
私は経験から、libC++の[現在のバージョン]では例外がスローされていることを知っています。ただし、すべて同じように未定義の動作これは信頼されるべきではありません。
この基本クラスのドキュメントには、shared_from_thisを呼び出す前にこの[オブジェクト]を所有する共有ポインタが必要であると記載されています。
大丈夫です。
[オブジェクト]をnewで割り当てても安全ですか?オブジェクトを管理するにはshared_from_thisを呼び出しますか?
いいえshared_from_thisを呼び出す前に、この[オブジェクト]を所有する共有ポインタが必要です。
shared_ptr
が所有していないインスタンスのshared_from_this
への呼び出しは、未定義の動作(通常は例外ですが、保証はありません)になります。
なぜ、もう一度答えますか?
私は一度自分自身に同じ質問をしたとほぼ同じ答えを得たので、私はその直後に発生した別の質問に苦しんで開始 - は、どのように私はすべてのインスタンスがshared_ptr
によって管理されているので、保証することができますか?
完全性のために、私はこの側面に関するいくつかの詳細と別の答えを追加します。
これまで説明していなかった単純な解決策です。
だから、シンプルなソリューション、実際:プライベートコンストラクタ、ファクトリメソッドと可変長テンプレート秒。
それは、最小限の例で一緒にそれらのすべてをミックススニペットを次に示します。
#include<memory>
#include<utility>
class C: public std::enable_shared_from_this<C> {
C() = default;
C(const C &) = default;
C(C &&) = default;
C& operator=(const C &) = default;
C& operator=(C &&c) = default;
public:
template<typename... Args>
static std::shared_ptr<C> create(Args&&... args) noexcept {
return std::shared_ptr<C>{new C{std::forward<Args>(args)...}};
}
std::shared_ptr<C> ptr() noexcept {
return shared_from_this();
}
};
int main() {
std::shared_ptr<C> c1 = C::create();
std::shared_ptr<C> c2 = C::create(*c1);
std::shared_ptr<C> c3 = c2->ptr();
// these won't work anymore...
// C c4{};
// std::shared_ptr<C> c5 = std::make_shared<C>();
// std::shared_ptr<C> c6{new C{}};
// C c7{*c1};
// ... and so on ...
}
基本的な(?些細な)アイデアは、新しいインスタンスの明示的な建設を禁止することであるが、ここで呼ばれるファクトリメソッドを使用してcreate
。
バリアントテンプレートは、いくつかのファクトリメソッドの作成を避けるために使用されます。パーフェクトフォワーディングは、正しい方法でこれを行うのに役立ちます。
かなりシンプルですね。
とにかくそれを理解するのはしばらく時間がかかりました。だから、これは将来の読者が同じ疑念の中で一度助けてくれることを願っています。
- 1. C++:オブジェクトへの共有ポインタではなく、共有オブジェクトを作成する
- 2. EWSマネージドAPIを使用して共有メールボックスを作成
- 3. C++継承と共有ポインタ
- 4. 共有ポインタ、バイナリツリーを返すC++ 11、
- 5. PthreadはCでポインタを持つ変数を共有します
- 6. C++で共有ポインタを扱いやすくする方法
- 7. ライブラリ間でFILEポインタを共有する
- 8. コンストラクタでshared_from_this()を使用する
- 9. 共有ポインタ
- 10. Objective-Cでスウィフト生成共有フレームワークを使用できない
- 11. 共有ポインタのC++スタックの削除
- 12. 共有ポインタを持つリストの共有ポインタ
- 13. Asio:例での自己共有ポインタの使用
- 14. 共有ポインタを返す
- 15. オブジェクトを共有するための共有メモリ(ポインタであるメンバーを含む)
- 16. interop(C++マネージド)プロジェクトでC#dll(Microsoft.bclで構築)を使用
- 17. 共有ポインタのソートリスト
- 18. ガベージコレクションと共有ポインタ
- 19. 共有ポインタとパフォーマンス
- 20. 共有メモリをPHPとCで使用していますか?
- 21. Cでのポインタの異なる使用
- 22. 関数ポインタの実装を上書きし、共有ライブラリ用に使用する
- 23. Parallel for C#で共有変数を使用する
- 24. 共有サービスを使用しないコントローラで共有サービスを使用するには?
- 25. CプログラムのC++共有オブジェクトを使用しますか?
- 26. 共有ライブラリ(旧スタンダード)をC++ 11共有ライブラリでコンパイルする
- 27. Cを使用して共有フォルダを作成する
- 28. c/C++で書かれた共有ライブラリを使用したLinux Cプログラム
- 29. 共有ポインタと生のポインタ寿命
- 30. Objective-C++での共有C++/STLコードの使用
test-> getptr()の呼び出しの後に、testを使って新しいポインタを管理し始めると、test2はどうなりますか?これは安全なユースケースですか? boost :: asioは、非同期の受信操作または書き込み操作を開始するときにこれらの構文を多く使用するため、これを求めています。 – Gustavo
@Gustavo 'getptr'の呼び出し後にポインタを管理することはできません。なぜなら、(shared_ptrによって)すでに管理されていなければ、ポインタを投げるからです。 – vitaut
私は次の場合を意味します: std :: shared_ptr test(new Test); std :: shared_ptr test2 = test-> getptr(); test.reset(new AnotherTest); /* test2で何かする*/ これは有効なユースケースですか? –
Gustavo