問題タブ [qsharedpointer]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票する
1 に答える
515 参照

c++ - QEnableSharedFromThis::sharedFromThis() は nullptr を返します

これをでラップしclass MyClassて返すことができるはずの があります。QSharedPointer<MyClass>

の新しいインスタンスを作成するだけではうまくいかないというのが私の理解 (および経験) ですQSharedPointer<MyClass>(this)。代わりに、私が望むことを達成する正しい方法は、メンバー関数を提供するためにMyClass継承させることです。QEnableSharedFromThis<MyClass>sharedFromThis()

このメンバー関数は、それ以外の場合に発生するすべての悪い副作用なしで、これをラップして返す必要があります。QSharedPointer<MyClass>

ただし、testSharedThis()上記の例を実行すると、 thisでラップされているのではなく、sharedFromThis()常にnullptrが返されます。QSharedPointer<MyClass>

私は初めてでQEnableSharedFromThis、欠けているものがあるかどうか疑問に思っていますか、それとも何が原因でしょうか?

0 投票する
1 に答える
592 参照

c++ - QSharedPointer でデストラクタを適切に使用する方法実行ループが停止した後?

おはようございます。

QSharedPointerから派生したクラスで使用していますQObject。これらはシグナル/スロット メカニズムを使用するQObject::deleteLater()ため、適切に破棄するには を使用する必要があります。例を参照してください。

~QObject() : "保留中のイベントが配信されるのを待っているときに QObject を削除すると、クラッシュが発生する可能性があります。現在実行中のスレッドとは別のスレッドに QObject が存在する場合は、QObject を直接削除しないでください。代わりに deleteLater() を使用してください。保留中のすべてのイベントがオブジェクトに配信された後、イベント ループによってオブジェクトが削除されます。」

QSharedPointer と QObject::deleteLater

QSharedPointer(X *ptr, Deleter d) : "deleter パラメーター d は、このオブジェクトのカスタム デリーターを指定します。カスタム デリーターは、強い参照カウントが 0 になると、演算子 delete() の代わりに呼び出されます。これは便利です。たとえば、代わりに QObject で deleteLater() を呼び出す場合"

また、前のリンクに書かれていることに注意してください

"カスタムのデリータ関数は、QSharedPointer テンプレート パラメータ T が同じでなくても、型 X へのポインタで呼び出されることに注意してください。",

しかし、これは次のように言うコンストラクタQSharedPointer(X *ptr)に関してはまったく異なる動作です。

「Qt 5.8 以降、この QSharedPointer への最後の参照が破棄されると、ptr は X のデストラクタを呼び出すことによって削除されます (X が QSharedPointer のテンプレート パラメータ T と同じでなくても)。以前は、T のデストラクタが呼び出されていました。」- (私は Qt 5.7 を使用しているので、~Tデストラクタを期待しています)

さて、最後に達成したいのは、を使用して(子クラスの)適切なデストラクタを呼び出すQSharedPointerことですが、それはQObjectを使用する必要があるためQObject::deleteLater()、テストでは目標を達成できません。

簡単なテストと結果を投稿します。

私が何か間違ったことをしている場合は教えていただけますか?

テストに期待することは正しいですか?

私が特に興味を持っているのは、「INTERESTING CASE」と書かれたケースです。

そして、これは結果です:

編集:

QObject::deleteLaterの動作、特に次のことを認識しています。

「メイン イベント ループが停止した後に deleteLater() が呼び出された場合、オブジェクトは削除されません。Qt 4.8 以降、イベント ループが実行されていないスレッドに存在するオブジェクトで deleteLater() が呼び出された場合、オブジェクトは削除されます。スレッドが終了すると破棄されます。」

しかし、私はQt 5.7を使用しているので、関数の最後にデストラクタが呼び出されることを期待しています.

編集 2

(タイトルも編集しました)

(質問は、予想以上に複雑になっているかもしれません。)

私の知る限り、メインスレッドはありません。すべてのスレッドは同等であり、メイン関数で暗黙的に作成される最初のスレッドでもあります。決して特別なものではないはずですよね?

では、なぜメイン スレッドを終了してもQSharedPointers が適切な方法で削除されないのでしょうか。

私が投稿したのはテストです。実際のアプリケーションではexec()ループがありますが、ループが停止した後にデストラクタが呼び出されます。

deleteLater()スレッドが終了したとき、つまりメインループを終了したときに s 関数が呼び出されることを期待しています。

PS: exec()@dave が言ったように、すべてのデストラクタを取得するためにループが必要でしたが、これはアプリケーションの 2 番目のループになります。

最後に の直前にreturn

なぜ必要なのですか?それを避けることは可能ですか?