web-dev-qa-db-ja.com

Qtで信号を送信するときのconst-ref

これは私がconst-refでまったく得られなかったことであり、誰かが私にそれを説明してくれることを本当に望んでいます。

別の関数内で関数を呼び出すと、改ざんする予定のないスタックオブジェクトを渡すときにconst-refが最良の方法であることがわかります。例えば:

void someInnerFunction(const QString& text) {
    qDebug() << text;
}

void someFunction() {
    QString test = "lala";
    ....
    someInnerFunction(test);
}

これまでのところ良いと思います。しかし、信号はどうですか?参照を渡すことに伴うリスクはありませんか? constですが。 const-refに関するすべてのドキュメントを読んでいるように感じますが、「オブジェクトへの参照を送信してconstを保持する」と理解しているため、まだ少し危険です。参照しているオブジェクトがスコープ外になった場合はどうなりますか?

例えば:

void someFunction() {
    connect(this, SIGNAL(someSignal(const QString&)), this, SLOT(someSlot(const QString&)));

    QString test = "lala";
    emit someSignal(test);

    // doesnt test go out of scope here? and since im not using queued connection the QString object doesnt get copied. 
}

void someSlot(const QString& test) {
    qDebug() << test; // will this work?
}

ここで実際に何が起こっているのですか?オブジェクトにアクセスしたいが変更したくない関数呼び出しでは、const-refを頻繁に使用します。しかし、信号はどうですか?ほとんどのシグナルはQtドキュメントにconst-refparmがあるようですが、どのように機能しますか?

27
chikuba

この回答 によると、Qtはconst参照をコピーに置き換えるだけです。

編集:どうやら常にそうであるとは限りません...私は1つのスレッドで基本的なテストプログラムを実行しただけで、参照は正しく渡されました。その恒常性も損なわれていません。とにかく、はい、変数がスコープ外になることに注意する必要があります。さらに、この方法でスレッド間で参照を送信することはできません。そうした場合、コピーのみが渡されます。

あなたの例のコメントの質問に答えるために、はい、それが直接接続であるかキュー接続であるかに関係なく機能します。直接接続の場合は、someSlot()が終了する前にsomeFunction()が実行されるため、機能します。キュー接続の場合は、testが参照によって渡されるのではなくコピーされるため、機能します。

21
Anthony

これは、Qtシグナル/スロットがコピーを管理する方法を示す良いデモンストレーションです: http://www.embeddeduse.com/2013/06/29/copied-or-not-copied-arguments-signals-slots/ ==

3
user2449761

Qtでは、1つまたは複数のスロットに接続されている信号を発信する場合、それは同期関数呼び出しと同等です...キュー接続を使用するように信号とスロットを構成していない限り、それは非同期呼び出しであり、スタックデータを渡すときは注意してください。別のスレッドにデータを渡す場合と同じようにコピーを渡す必要があります。

0
syplex