15

QObject から派生したオブジェクトが破壊されている場合、そのデストラクタからシグナルを発しても問題ありませんか? 私はそれを試してみましたが、うまくいくようですが、それを行うべきかどうかはわかりません。

たとえば、このコード

class MyClass : public QObject {
signals:
    void mySignal(const QString &str);
public:
    QString myString;
    ~MyClass() { emit mySignal(myString); }
}

接続されたスロットが実行されるまでに範囲外になる可能性のあるオブジェクトへの const 参照を渡します。

4

2 に答える 2

14

エミッションは一般的に問題ありません(QObjectは「破壊された」シグナルでも行います)。これには、あなたのケースも含まれます。接続が直接の場合、文字列はまだ有効です。QueuedConnection の場合は、最初に文字列がイベント ループにコピーされます。

于 2012-12-24T19:14:37.493 に答える
5

大丈夫ですか? はい、それ自体は問題ありません。

Qtで行うのが一般的に安全なことであるかどうかを尋ねるとしたら? 間違いなく安全ではありません。デストラクタからエミットする場合は、何をすべきか非常に注意する必要があり、Qt イベント システムを十分に理解している必要があります。

QObject子孫が破棄されると、すべてのシグナルが切断されるため、破棄されたオブジェクトはスロットでそれ以上呼び出しを受けないことを覚えていますか? 落とし穴があります: 破壊命令です。デストラクタはその切断を行い、QObject破壊するのは最後です。つまり、破壊チェーンでイベントが「半死半生」のオブジェクトに到達し、仮想関数や既に破壊された子孫のメンバーにアクセスするときにアクセス違反が発生する可能性があります。イベント システムを使用していて、次の条件のいずれかが満たされている場合、可能性があります。

  • マルチスレッド環境で、オブジェクトが独自のスレッドで破棄されない場合。
  • マルチスレッド環境で、オブジェクトの破棄チェーンがprocessEvents()任意の実行パスでの実行をトリガーする場合。
  • マルチスレッド環境で、別のスレッド上のオブジェクトにこのオブジェクトへの直接接続があり、直接接続で破棄されたシグナルに反応しない場合。
  • シングル スレッド環境で、デストラクタがシグナルを送信すると、ダイレクト コネクト チェーンでオブジェクトに返される可能性があります。

私はこの効果を「死の間の生」と呼んでおり、デストラクタでシグナルを発したり、何らかの形でprocessEvents()(通常は偶発的に) 実行したりすると、このようなエラーが発生する可能性が高くなります。

もちろん、現在または将来のコードが実際に破棄中にスロットをトリガーしないことを何らかの方法で保証できる場合、デストラクタから発行することは完全に安全ですが、そのような保証を与えることは非常に困難であり、可能な限りそれを避けることをお勧めします.

于 2017-02-16T09:13:15.703 に答える