【问题标题】:const-ref when sending signals in Qt在 Qt 中发送信号时的 const-ref
【发布时间】:2012-05-11 10:54:37
【问题描述】:

这是我在 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 parm,但它是如何工作的?

【问题讨论】:

  • “当在另一个函数内部调用一个函数时,我知道 const-ref 是传递对象时的最佳方式。” 这是一个非常通用的方法回答一个基本的 C++ 问题,谁告诉你的?
  • 我的意思是如果你不打算改变它们。好像qt到处都在使用这种方法,是的,我不是到处都这样做。但是什么时候不好呢?我只谈论我不想将它们复制到函数的堆栈对象
  • 基本上认为,当必须将堆栈对象作为 in-parm 传递时,以下讨论是有趣的。 stackoverflow.com/questions/270408/… 但我的问题更多的是如何处理信号,因为某些 ppl 声明它应该由 const-ref 完成,这样我们就不必复制对象
  • 对于直接连接,发出的信号只是围绕 Qt 为您调用一个或多个槽函数的语法糖,因此它的工作方式与调用普通 C++ 方法的方式相同(除了没有返回值当然,被传递回调用者)。对于排队的连接,Qt 无论如何都会复制参数。

标签: c++ qt signals-slots const-reference pass-by-const-reference


【解决方案1】:

根据this answer,Qt 只是将 const 引用替换为副本。

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

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

【讨论】:

  • 你在哪里读到的?我所看到的只是“对于直接连接,建议通过 const 引用传递值以避免不必要的复制。对于排队的连接,无论您如何传递参数,Qt 都会进行复制”
  • “无论如何,是的,您确实需要警惕超出范围的变量”-除非您通过指针传递对象,否则我看不出这应该是什么问题。
  • 感谢您为您的回答付出了很多努力,并且您一直在更改它,直到您做对了(我希望:p)
  • @jan 2016 似乎 trolltech.com 已不复存在。 RIP。
【解决方案2】:

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

【讨论】:

  • 引用所提供链接的结论可能有用:“结论 [...] 是我们应该通过 const 引用而不是通过值将参数传递给信号和槽"
【解决方案3】:

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

【讨论】:

  • 通过 const refs 传递的对象仅被复制用于异步(排队)连接。堆栈数据超出范围没有危险,除非您通过指针传递它们。
猜你喜欢
  • 1970-01-01
  • 2011-08-12
  • 2015-05-06
  • 2012-03-13
  • 2011-03-12
  • 2012-03-27
  • 2011-04-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多