17

ここで、私のシグナル宣言:

signals:
    void mySignal(MyClass *);

そして、私がそれをどのように使用しているか:

MyClass *myObject=new myClass();
emit mySignal(myObject);

ここに私の問題があります:myObjectの削除の責任者は誰ですか?

  1. 送信者コード、myObjectが使用される前に削除された場合はどうなりますか?ダングリングポインタ

  2. 信号に接続されているスロット、信号に接続されているスロットがないか、複数のスロットがある場合はどうなりますか?メモリリークまたはダングリングポインタ

Qtは組み込みシグナルでこの状況をどのように管理しますか?内部参照カウントを使用していますか?

あなたのベストプラクティスは何ですか?

4

4 に答える 4

10

信号は必要な数のスロットに接続できるため、これらのスロットのいずれも、オブジェクトで実行したくないことを実行できないことを確認する必要があります。

  • パラメータとしてポインタを渡すことにした場合は、説明した問題、メモリ管理で実行されます。ここでは、割り当て/削除を処理するためのポリシーを確立する必要があるため、誰もあなたのために作業することはできません。これに対処する方法に関するいくつかのアイデアについては、COMの世界のメモリ管理ルールを参照してください。
  • パラメータを参照として渡すことにした場合は、メモリ管理について心配する必要はありませんが、スロットが予期しない方法でオブジェクトを変更することだけを心配する必要があります。アイデアは、必要がない限りポインタを渡さないことです。代わりに、可能であれば参照を使用してください。
  • 参照を渡すことにした場合const、接続タイプに応じて、QTはオブジェクトの値を渡します(詳細については、これを参照してください)。
  • 問題を回避し、値を渡します:)

シグナルでポインターを渡すことについてのいくつかの考えについては、この質問も参照してください。

于 2010-07-06T06:44:56.033 に答える
5

最初の質問には、QPointerを使用してください

2番目の質問については、

私がはっきりと理解していれば、送信しているmyObject場合でも、シグナルを送信しているクラスに参照があります。 myObjectでは、メモリリークやダングリングポインタはどうなるのでしょうか。放出されたクラスからは引き続きアクセスできますね。myObject

明確に願っています。

編集 :

あなたのコメントから、あなたはスロット内のオブジェクトを解放/削除していると思います。ここで、あなたの問題は、(メモリ解放)スロットが1回呼び出された場合、2回呼び出された場合、またはまったく呼び出されなかった場合はどうなるかということだと思います。

そのためにQPointerを使用できます。Qtのドキュメントから、

保護されたポインタ( )は、他の誰かが所有しているQPointerへのポインタを格納する必要がある場合に役立ちます。したがって、そのポインタへの参照を保持している間は破棄される可能性があります。QObjectポインタの有効性を安全にテストできます。

Qtドキュメント自体からの例、

     QPointer<QLabel> label = new QLabel;
     label->setText("&Status:");
     ...
     if (label)
         label->show();

説明はこのように続きます。

その間にQLabelが削除されると、ラベル変数は無効なアドレスではなく0を保持し、最後の行が実行されることはありません。ここで、QLabelはあなたにMyClassなり、labelはあなたになりますmyObject。そして、それを使用する前に、Nullityをチェックしてください。

于 2010-07-06T06:43:16.930 に答える
3

1):送信者は注意する必要があります。信号を(キューに入れられる代わりに)同期的に送信する場合、受信者が信号を受信したときにオブジェクトはまだ生きています。受信者がそれを保存する必要がある場合、QPointerのみが役立ちますが、MyClassはQObjectから派生する必要があり、コンテキストからは間違っているように見えます。とにかく、それは一般的な生涯の問題であり、信号/スロット固有ではありません。

代替方法:値クラスを使用して、const参照を介して送信します。MyClassがサブクラスを持つことができる場合は、const QSharedPointer&を渡します。

deleteLaterについて:deleteLater()はここでは役に立ちません。キューに入れられた接続がより安全になり、直接接続の場合は違いはありません。deleteLater()が機能する1つの用途は、受信者が送信者を削除する必要がある場合です。次に、送信者が自分が行っていたことを完了できるように、常にdeleteLater()を使用する必要があります。そうしないと、クラッシュします。

于 2010-07-06T07:03:50.713 に答える
0

一言で言えば(わかりました、関数名)-deleteLater():)すべてのQObjectにあります。オブジェクトに削除のマークが付けられ、これは次のイベントループの更新時に発生します。

于 2010-07-06T06:06:54.367 に答える