我读到QT在信号/插槽机制上应用了签名规范化过程。 MOC生成器基本上从信号/槽中移除const引用限定符,并按值传递它们。
我有一个类,它会频繁生成一个名为BIG_DATA的大数据结构,而其他一些类每次发出时都需要捕获这个数据结构。
struct BIG_DATA
{
// very big data
};
class DataGenerator
{
// some methods which generate BIG_DATA
signals:
void data_updated(const BIG_DATA &);
};
我做什么:
connect(&data_generator_object, SIGNAL(data_updated(const BIG_DATA &)), this, SLOT(catch_new_data(const BIG_DATA &)));
QT的作用:
connect(&data_generator_object, SIGNAL(data_updated(BIG_DATA)), this, SLOT(catch_new_data(BIG_DATA)));
那么,在这里删除const引用限定符有什么好处?我将如何处理将整个BIG_DATA复制到data_updated信号的许多客户端的开销?
似乎最好的方法是使用指向生成的BIG_DATA对象的指针,如果QT也没有尝试删除指针签名。
答案 0 :(得分:2)
签名规范化仅用于识别信号和时隙。也就是说,如果您想告诉connect()
使用哪个信号或插槽,则需要在那里传递规范化签名。但是你的信号和插槽的签名仍未触及。如果使用直接连接(这是单线程程序的默认设置),则不会复制您的对象。
答案 1 :(得分:2)
如果您使用排队连接,则无论如何都会复制您的结构(请参阅this)。
现在,如果您使用标准化信号,则可以在使用connect(see this)时将性能降至最低:
首先尝试使用签名原样进行查找,并且只有在失败的情况下才会调用QMetaObject :: normalizedSignature()。
这意味着,当使用非规范化的信号/插槽签名时,您不仅要支付strcpy(),还要支付注定要失败的首次查找尝试。当然,连接通常在启动期间完成,并且探查器不会向您显示,但是使用非规范化签名因此被牢牢地置于过早悲观化的范围内。
然而,只有在使用连接时才会出现性能损失,而不是在发送信号时。并且连接通常只进行一次。所以我不会太担心。
为了避免结构复制,请使用引用。