Qtを使ってプログラミングしているときは、この問題はいつも問題になります。 Qtはオブジェクト所有権ツリーを使用しているため、ポインタを渡します。 myBoostSharedPtr.get()
を介して暗黙的に所有権を譲渡することができます。 いくつかのQtオブジェクトが破棄され、オブジェクトツリー全体が破棄されるがスマートポインタがまだ生きている場合を考えてみましょう。別のクラスのメンバとして その後スマートポインタが削除されるとどうなりますか? すべての厄介な結果を伴うダブル削除? スマートポインタの実装によってこれが防止されていますか?スマートポインタが保持するオブジェクトが他の場所で削除されるとどうなりますか?
答えて
私は、Qtのメモリモデルの弱点を突きつけて、ポインタを受け入れたQObjectがそれを削除している間に、クライアントがそれを割り当てても、未処理のポインタを受け入れることができます。
ご質問に対する回答は、です。未定義の動作です。 shared_ptr
は、ポインタがshared_ptr以外のものによって削除されたかどうかを検出するメカニズムを持っていないので、通常はポインタをもう一度解放しようとします(ダングリングポインタでdeleteを呼び出します)。 shared_ptrを使いたい場合は、単独のメモリマネージャとしてshared_ptrを使用する必要があります。これはQt自身のQSharedPointer
でも当てはまります。私は通常、Qtのようなものを使用した場合、合理的に例外セーフな私のコードを取得しようとするやった
は(unique_ptr
がそれに取って代わると、使用可能なC++ 11を持っている場合ははるかに安全である)廃止auto_ptr
を使用することでした。それはrelease
メソッドを提供するので、私が今までauto_ptr
を使用するように誘惑された唯一の場所です。
unique_ptr<QListWidget> widget(new QListWidget(...));
// do stuff with the widget to set it up for your GUI
some_layout.addWidget(widget.release()); // <-- release ownership so that
// the layout now becomes responsible
// for memory management
// ^^ auto_ptr works above if we don't have C++11
あなたはそれがすでにQtのことで、メモリ管理された後、あなたのオブジェクトに永続的なポインタを保持する必要がある場合(例:あなたはレイアウトに挿入した後、あなたのウィジェットへのポインタ)だけで、通常のポインタを使用し、 。 Qtがそのオブジェクトのメモリマネージャになって以来、あなたができることはあまり良くありません。
しかし、QObject::destroyed
信号でオブジェクトが破棄されたとき(したがってポインタが無効になったとき)を検出できます。
本当に洗練されたものにしたい場合は、QObjectのサブクラスのみを格納する共有ポインタ型を作成できます。 QObjectは破壊された信号を提供するので、この種類のカスタムスマートポインタは、QObjectが破棄信号によって破壊されたときに検出し、オブジェクトを2度目に削除しようとしないようにすることができます。しかし、マルチスレッドコードではこの信号に頼りになるかもしれません。共有ポインタを実装すると、ポインタが構築されているサイトで削除関数をキャプチャして、アトミックな参照カウントを処理することにかなりの負担になる可能性があります
私はあなたが引数リストで解放すべきだとは思わない。 'addWidget'がポインタを引き継ぐ前にスローすると、あなたはリークしました。 – GManNickG
@GmanNickGそれは良い点です。あなたは、呼び出しが成功した後にのみ私たちが解放すべきだと思いますか?私はそれを見て、APIはクライアントによって割り当てられたメモリへの生ポインタを受け取ります。一度渡したら、* addWidget *で例外が発生した場合、ポインタのdeleteを呼び出すのはQTの責任です。 QTがaddWidget内のローカルtry/catchブロックでポインタを削除することによってその条件を処理しようとしているかどうかはドキュメントに記載されていません。 addWidgetでポインタを削除して再スローすると、私のunique_ptrがdeleteを呼び出す可能性があります。 – stinky472
@GManNickG ...ぶら下がりポインタです。 addWidgetの実装方法について私が知っていることに非常に依存します。 – stinky472
はい、ほとんどの可能性がありますし、そうでない場合もありません。どのように表示されるのかわかりません。あなたは、ポインタを渡しているものが所有権を取らないということを契約書に頼らざるを得ません(ドキュメントに書かれている場合を除きます)。後者の場合は、あなたの側のスマートポインタにそれをラップしません。
親QObjectとスマートポインタの間で共有所有権を持たず、他のスマートポインタを削除することはできませんが、QWeakPointer
のみを使用して、QObject
の削除を追跡できます(またはQPointer
)。
は更新http://qt-project.org/doc/qt-4.8/qweakpointer.html#tracking-qobject
を参照してください:Qtの5では、QWeakPointer
でQSharedPointer
で管理されていないQObject
Sを追跡すること(undeprecatedそのものである)QPointer
の賛成で廃止されました。
あなたはしないでください。 'QSharedPointer'を使わずに' QWeakPointer'を使うことは、非常に良い理由のために廃止されました。なぜなら、それは_C++ 11_にないのと同じ理由です。 – abergmeier
@abergmeierコメントを残すだけでなく、あなた自身で答えを更新するのではなく、なぜあなたがダウン投票したのか分かりません。 QObject追跡の目的で 'QWeakPointer'を使うことは、書面の時には推奨された方法でした。 – alexisdm
- 1. コールバックを持つ別のオブジェクトが所有するオブジェクトを、削除するオブジェクトから削除できますか?
- 2. Github - ユーザーが削除された場合のコミットはどうなりますか?
- 3. ライブアプリケーションのプロビジョニングプロファイルが削除された場合はどうなりますか?
- 4. フレームワークがアプリから削除されるとどうなりますか?
- 5. EclipseでDFSの場所が削除されない
- 6. XCode 5が削除されるようですInstallationBuildProducts Archiveの場所
- 7. オブジェクトを削除するCoreDataGeneratedAccessorsが削除されていないようです
- 8. AS3 - コードを実行しているオブジェクトが削除されるとどうなりますか?
- 9. 別の場所のポインタを削除すると、動作が異なる(クラッシュするかどうか)
- 10. With ActiveRecord has_many relationshipsどのようにオブジェクトを保持しながら関連を削除するのですか?
- 11. 存在するかどうか:1つのオブジェクトが所有するスマートポインタがアクセスを許可する
- 12. iOS:Core Dataからオブジェクトを削除すると、テーブルビューで削除されますが、他のアプリでは削除されません
- 13. モデルがDjango Adminや他の場所から保存されたかどうかを確認する方法
- 14. Androidのタスクマネージャからアプリが削除されたときにコードが実行されなくなる場所
- 15. 行Xの行を保持し、パターンが含まれていない場合は他を削除します。
- 16. 保護されたデストラクタを持つオブジェクトを削除する
- 17. 仮想デストラクタを持たない多相オブジェクトを削除するとどうなりますか?次の例で
- 18. オブジェクトの所有権 - どのウィジェットがそれを削除すべきですか?
- 19. 削除する場所
- 20. InvalidOperationException - オブジェクトが現在他の場所で使用されています
- 21. アプリケーションを削除するとドキュメントフォルダが削除されますか?
- 22. MS SQL datetime:hh:mm:ssがEntity Frameworkコアで保持されている場合に削除されます。
- 23. C#リスト<T>からアイテムを削除すると、他のアイテムの注文は保持されますか?
- 24. Ubuntuでメインプロファイルを削除するとどうなりますか?
- 25. 整合性を保持しながらオブジェクトグラフからオブジェクトを削除する
- 26. do-whileが再び開始されるとオブジェクトが削除されます。どうすればそれを止めることができますか?
- 27. アプリケーションからコアの場所が削除されましたが、依然としてユーザーの場所が要求されています
- 28. ビルドが削除されたときにTFS 2017ビルドvnextでネットワークドロップの場所とシンボルがクリーンアップされない
- 29. どのようにスマートポインタなしでダブル削除を防止するには?
- 30. const参照がない場合、一時オブジェクトは削除されますか?
私は実際には、QSharedPointerでこの種の問題に遭遇しました。概念的には、boostの 'shared_ptr'と非常によく似ています。私は自分の所見に関するブログエントリを書いた:http://blog.codef00.com/2011/12/15/not-so-much-fun-with-qsharedpointer/ –