在Qt中发送信号时的const-ref

const-ref when sending signals in Qt

本文关键字:const-ref 信号 Qt      更新时间:2023-10-16

这是我对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-ref参数,但它是如何工作的呢?

根据这个答案,Qt只是用副本替换了const引用。

编辑:显然并非总是如此...我刚刚用一个线程做了一个基本的测试程序,引用被正确传递。它的恒定性也保持不变。无论如何,是的,您确实需要警惕变量超出范围,而且您不能以这种方式跨线程发送引用。如果这样做,则只会传递副本。

要回答示例注释中的问题,是的,无论是直接连接还是排队连接,它都可以工作。如果是直接连接,它将起作用,因为someSlot()将在someFunction()完成之前执行;如果它是排队的连接,它将起作用,因为test将被复制而不是通过引用传递。

这里有一个很好的演示,展示了Qt信号/插槽如何管理复制: http://www.embeddeduse.com/2013/06/29/copied-or-not-copied-arguments-signals-slots/

在Qt中,当发出连接到一个或多个插槽的信号时,它相当于同步函数调用...除非您已将信号和槽配置为使用排队连接,否则它是一个异步调用,在传递堆栈数据时应小心,并且应该像将数据传递到另一个线程一样传递副本。