QT 信号与槽的参数转存(转载)

信号与槽的连接有Qt::DirectConnection, Qt::QueuedConnection等模式,用Qt::QueuedConnection模式的话,信号与槽之间的参数就有可能需要转存了。
例如:
typedef struct my_type
{
   QString q_str;
    int i;
}MY_TYPE;

signals: signal_method(MY_TYPE str )

slot: slot_method(MY_TYPE str )

QT会把信号发过来的参数拷贝一份,然后等槽要执行的时候,交给槽。

但如果我们定义信号、槽的时候,若果用的是引用参数,情况又会如何? 从测试来看,QT不会拷贝参数。这也符合引用的使用。但问题来了,信号传递过来的引用是局部变量,信号发射完就过了生命周期,这样槽执行拿到的引用还会有效吗? 测试的结果来看,信号传递的引用过了生命周期,但槽还能拿到引用的内容。

C++的引用像unix 文件系统 硬链接还是软连接呢?

#include <QtGui/QApplication>
#include "iostream"
#include "qdebug"

using namespace std;

typedef struct aa
{
    QString q_str;
    int i;
}AA;

AA t3;

AA &t =  t3;

void pass();

int main(int argc, char *argv[])
{

    pass();

    cout << qPrintable(t.q_str) << endl;

    int ci;
    cin >> ci;

}


void pass()
{
    AA *t2 = new AA();
    t2->i = 5;
    t2->q_str = "my test str";

    t = *t2;

    delete t2;
}

结果的输出为何还是"my test str"? 是delete 没有重置 t2指向的内存?

shiroki2009-08-27 13:35
引用类似于指针, 应该算软连接
AA &t =  t3; 这句话类似于让t指向t3的地址
t = *t2; 这句话则类似于把t2的内容复制给t3.
所以delete t2不会对t有影响

你可以查查t3的内容, 看看是不是这样

jasonhit2009-08-27 15:16
引用
引用第1楼shiroki于2009-08-27 13:35发表的  :
引用类似于指针, 应该算软连接
AA &t =  t3; 这句话类似于让t指向t3的地址
t = *t2; 这句话则类似于把t2的内容复制给t3.
所以delete t2不会对t有影响

.......


谢谢shiroki。

恩,应该是这样的。


至于信号与槽的参数,在connect的时候好像是不支持引用的。也就是connect(this, SIGNAL(sender(MY_TYPE &)), this, SLOT(receiver(MY_TYPE &))), 这里用MY_TYPE &是有错的,但用MY_TYPE * 就可以。

shiroki2009-08-27 15:27
不会呀, qt本身的信号和槽有很多用到引用的. 比如 Model的index经常用引用传来传去的. 估计你的程序什么地方写错了吧

jasonhit2009-08-28 11:01
引用
引用第3楼shiroki于2009-08-27 15:27发表的  :
不会呀, qt本身的信号和槽有很多用到引用的. 比如 Model的index经常用引用传来传去的. 估计你的程序什么地方写错了吧



恩,确实是搞错了,QT的信号与槽的参数如果是引用的话,得加const 才行。

在信号与槽的参数中,用引用与用指针在转存参数的时候是有区别的。用引用的话,在转存参数的时候,QT还是会把参数拷贝出来,这点可以用局部变量测试出来。因为用局部变量,用引用的话,可以把参数从信号传递到槽,而用指针的话,则出错。

shiroki2009-08-28 11:24
事实证明,你的理解仍然有问题。 还是检查检查你的程序哪里写错了吧

jasonhit2009-08-28 12:26
引用
引用第5楼shiroki于2009-08-28 11:24发表的  :
事实证明,你的理解仍然有问题。 还是检查检查你的程序哪里写错了吧



shiroki,非常感谢你的例子。

是的,没错,当QT的信号与槽的参数不需要转存的时候是可以不用加const的。但参数需要用转存的时候就不行了。

我把connect(this, SIGNAL(sigTryMe(QImage&)), this, SLOT(sloTryMe(QImage&)), Qt::QueuedConnection); 加上了Qt::QueuedConnection,程序运行就不正确了。QT4.5默认是auto的,也就是在同一个线程里面,是用DirectConnection,但不同线程里面是用QueuedConnection的。所以在Qt::QueuedConnection的参数就需要转存了,也就是QT需要把信号发过来的参数先缓存起来,等到调用槽的时候,再把参数取出来,交给槽去运行。在转存的时候,当参数是引用的时候,QT是如何去缓存那些参数的呢?我测试来看,是拷贝的。

当connect的时候用上了Qt::QueuedConnection,则需要在信号、槽的参数加上const,那样程序又运行正确了。


环境:QT 4.5, qt-add-in, vs2005

shiroki2009-08-28 13:33
恩, 这个问题主要是变量运行期的问题。  queuedconnection等到slot调用的时候参数的运行期已经过了,引用就无效了。
至于变成const,const变量在单独的常量区定义(不在stack里), 整个程序的生命周期都是有效的, 和普通的auto变量不太一样。 我觉得应该是这一点造成的结果。
不管如何传引用的话应该由程序去保证参数的有效性。

jasonhit2009-08-28 14:53
难道说,函数的引用参数,加上const,使得实参的生命周期不一样了? 这点不太好理解了。

beajisong2009-08-29 21:24
QT在传参的过程中,有时向上面所述是需要转储参数
但是
const QString& 和QString两类参数在对待上并没有区别
这也是为啥上面有人说非要const的问题
而且转储参数必须为QT已识别的类型,也就是说QMeta系统了解的。
自定义类型需要注册一下
而且,因为是转储还需要提供拷贝构造函数和赋值操作符
最后,常引用和局部变量参数都是转储拷贝对象。

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值