6
// Example class
class A : public QObject
{
   Q_OBJECT
   void fun() {
       Timer::SingleShot(10, timerSlot); //rough code
   }
   public slot:
   void timerSlot();
}

auto a = SharedPointer<A>(new A);
a->fun();
a->reset(); // a deleted

この場合、 a が削除され、タイマーが起動された後、実行されtimerSlot()ますか? 非常にまれなクラッシュが発生していますが、それがこのロジックの怪しいものによるものかどうかはわかりません。

4

5 に答える 5

9

タイマーが起動しても、スロットはトリガーされません。状態のドキュメント~QObject:オブジェクトとの間のすべての信号は自動的に切断され、オブジェクトの保留中のポストされたイベントはイベント キューから削除されます。A::timerSlotと削除Aを同時にトリガーできる唯一の方法は、スレッドを使用する場合です。

于 2016-06-17T08:01:59.127 に答える
2

オブジェクトを削除する前に、オブジェクトのシグナルとスロットを切断する義務はありません。

QObject デストラクタは、次の場合に限り、廃止されたシグナルスロット接続をクリーンアップします。

  1. QObject から継承

  2. クラス定義で Q_OBJECT マクロを使用する

destroyed()これらの規則に従うことで、オブジェクトが削除されたときにシグナルを発することが保証されます。これは実際に、Qt のシグナルとスロットのシステムがダングリング リファレンスをクリーンアップするために使用するものです。

destroyed()オブジェクトのライフサイクルを追跡するためのデバッグ コードを追加したい場合は、自分でシグナルを聞くことができます。

(使用している Qt/moc の特定のバージョンによっては、スロットを使用する QObject 以外のコード、またはヘッダーに Q_OBJECT を持たない QObject 派生クラスを含むコードがコンパイルされても、timerSlot()メソッドが実行時にガベージ ポインターで呼び出されます。)

于 2016-06-17T02:01:11.713 に答える
0

編集:この回答は、使用しなかったが何も継承しないスタンドアロンクラスとしてQObject持っていた元の質問への回答でした。class A質問は後で編集され、この回答は廃止されましたが、使用しない場合に何が必要になるかを示すためにここに残しますQObject


これを行う唯一の方法は、タイマーが作動するまでオブジェクトを存続させることです。例えば:

class A : enable_shared_from_this<A> {
   void fun() {
       QTimer::singleShot(10, bind(&A::timerSlot, shared_from_this()));
   }
public:
   void timerSlot();
}

auto a = SharedPointer<A>(new A);
a->fun();
a->reset(); // a goes out of scope, but its referent is kept alive by the `QTimer`.

上記が機能する理由はclass A、タイマーを設定するときに shared_ptr をキャプチャし、タイマーがそれを保持するためです (それ以外の場合は起動できません)。

最新の C++ 機能または Boost が気に入らない、または使用できない場合:

struct Functor {
    Functor(SharedPointer<A> a) : _a(a) {}
    void operator() { a->timerSlot(); }
    SharedPointer _a;
};

class A {
   void fun(shared_ptr<A> self) {
       QTimer::singleShot(10, Functor(self));
   }
public:
   void timerSlot();
}

auto a = SharedPointer<A>(new A);
a->fun(a);
于 2016-06-17T01:34:58.250 に答える