Qtライブラリに関する公式の例とチュートリアルがスマートポインターを使用しないのはなぜですか?ウィジェットの作成と破棄については、new
とdelete
のみが表示されます。
私は理論的根拠を検索しましたが、それを見つけることができませんでした。歴史的な理由または後方互換性のためである場合を除き、自分自身は見当たりません:ウィジェットコンストラクターが失敗した場合にプログラムを終了させ、try/catchを介して処理することを誰もが望んでいませんブロックはjustいだけです(いくつかの場所で使用されている場合でも)。親ウィジェットが子の所有権を取得する可能性があるという事実も、一部のレベルで親にdelete
を使用する必要があるため、部分的にしか説明しません。
QtはQobjectリソースを管理するために親子モデルに依存しているためです。イベント管理からメモリ管理、描画、ファイル処理などに使用される複合+責任の連鎖パターンに従います。
実際、共有\一意のポインターでQObjectを使用しようとすると、オーバーエンジニアリング(99%の確率)になります。
deleteLater
を直接呼び出すことができます。ただし、QtでRAIIを引き続き使用できます。たとえば、 QPointer はQObject
の弱参照として動作します。私は使うだろう QPointer<QWidget>
のではなく QWidget*
。
注:2つの単語:Qt + valgrind。
スマートポインタークラス_std::unique_ptr
_および_std::shared_ptr
_は、メモリ管理用です。このようなスマートポインターがあるということは、ownポインターであることを意味します。ただし、QObject
またはQObject
親を持つ派生型を作成する場合、所有権(クリーンアップの責任)は親QObject
に引き継がれます。その場合、標準ライブラリのスマートポインターは、二重削除を引き起こす可能性があるため、不要であるか、さらには危険です。いいね!
ただし、親QObject
なしでヒープにQObject
(または派生型)が作成されると、状況は大きく異なります。その場合、生のポインタだけでなく、スマートポインタ、できればオブジェクトへの_std::unique_ptr
_を保持する必要があります。そうすれば、リソースの安全性を確保できます。後でオブジェクトの所有権を親QObject
に渡す場合、std::unique_ptr<T>::release()
を次のように使用できます。
_auto obj = std::make_unique<MyObject>();
// ... do some stuff that might throw ...
QObject parentObject;
obj->setParent( &parentObject );
obj.release();
_
親を親に渡す前に行うことで例外がスローされる場合、オブジェクトを保持するために生のポインタを使用すると、メモリリークが発生します。ただし、上記のコードはこのようなリークを防ぐためのものです。
生のポインタをすべて一緒に避けることは現代のC++のアドバイスではなく、owning生のポインタを避けることです。別の最新のC++アドバイスを追加する場合があります:他のプログラムエンティティが所有するオブジェクトにはスマートポインターを使用しないでください。
あなたはすでにあなた自身の質問に答えました:except if it's for historic reasons/backward compatibility
。 QTと同じくらい巨大なライブラリは、そのライブラリを使用するすべての人がC++ 11をサポートするコンパイラを持っていると想定することはできません。 new
およびdelete
は、以前の標準に存在することが保証されています。
ただし、スマートポインターの使用をサポートしている場合は、未加工のポインターよりもスマートポインターを使用することをお勧めします。
@Jameyが言ったことに加えて:
巧妙に設計すれば、ウィジェットで削除を使用する必要がなくなる可能性があります。メインウィンドウがあり、その自動オブジェクトを作成し、イベントループでそのウィンドウを実行しているとします。これで、このウィジェットのすべてのアイテムを子として追加できます。そして、これらをMainWindowに直接/間接的に子として追加するため、このメインウィンドウを閉じると、すべてが自動的に処理されます。作成したすべての動的オブジェクト/ウィジェットがMainWindowの子/孫であることを確認する必要があります。したがって、明示的な削除の必要はありません。
QObject
には親が定義されており、プログラムのツリーのような構造により、メモリを非常に効果的に管理できます。
Qtのダイナミズムは、ニースの理想を打ち破ります。生のポインタを渡します。 dangling pointer
を保持することは簡単ですが、それはプログラミングの一般的な問題です。
実際には弱い参照であるQtスマートポインターはQPointer<T>
です
そしてSTLキャンディーの一部を提供します。
std::unique_ptr
などと混合することもできますが、プログラムのQt以外の機械にのみ使用してください。