私は、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. PthreadはCでポインタを持つ変数を共有します
- 3. ライブラリ間でFILEポインタを共有する
- 4. C++で共有ポインタを扱いやすくする方法
- 5. Asio:例での自己共有ポインタの使用
- 6. 共有ポインタとパフォーマンス
- 7. ガベージコレクションと共有ポインタ
- 8. 共有メモリをPHPとCで使用していますか?
- 9. Parallel for C#で共有変数を使用する
- 10. CプログラムのC++共有オブジェクトを使用しますか?
- 11. Cを使用して共有フォルダを作成する
- 12. c/C++で書かれた共有ライブラリを使用したLinux Cプログラム
- 13. C#ASP.NETを使用してネットワーク共有にアクセスする
- 14. shared_from_thisをコールバックインターフェイスオブジェクトで使用できないのはなぜですか?
- 15. dlopenと共有オブジェクトのポインタ
- 16. Objective-C++での共有C++/STLコードの使用
- 17. C++でスレッドを共有するスレッド
- 18. Haskellでスレッドセーフな共有変数を使用する方法
- 19. Visual Cのダイナミックリンクライブラリで共有メモリを使用
- 20. エラーVS2010で使用するMATLABでC共有ライブラリを作成中に
- 21. ビデオカード:共有システムメモリと使用可能なメモリの合計をC#
- 22. PerlでDynaLoader.pmを使用してAda共有オブジェクトをロードする
- 23. C++用分散共有メモリライブラリ?
- 24. C++での偽の共有
- 25. fork()で共有メモリを使用
- 26. Alfrescoで設定値を保存して使用する共有
- 27. C#でWeb共有を作成するとエラーなしで失敗する
- 28. C++ - スマートポインタ - テンプレートを介してベースクラスへの共有クラスのポインタを渡す
- 29. 共有マルチプラットフォームPOSIX環境でのCの使用
- 30. godaddy共有ホスティングでaspフォームプロジェクトでjQueryを使用するAJAXを使用する
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