Qt使用信号槽传递大量数据的效率问题

5 篇文章 0 订阅

1. 隐式共享

之前一直担心Qt中的信号槽在传递大量数据下的情况下复制拷贝产生的效率问题,还转而使用指针去传递。实际上因为Qt中的隐式共享的技术完全不用担心此问题。不过值得注意的是隐式共享的条件和使用规则,而且也并非所有的结构都支持隐式共享。

#include <QCoreApplication>
#include <QDebug>

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

    QByteArray b1 = "hello world";
    QByteArray b2 = b1;

    qDebug() << "0x" + QString::number(reinterpret_cast<qintptr>(b1.constData()),16);
    qDebug() << "0x" + QString::number(reinterpret_cast<qintptr>(b2.constData()),16);

    b2 = "你好,世界";

    qDebug() << Qt::endl;
    qDebug() << "0x" + QString::number(reinterpret_cast<qintptr>(b1.constData()),16);
    qDebug() << "0x" + QString::number(reinterpret_cast<qintptr>(b2.constData()),16);

    return a.exec();
}

输出:

"0x1b6558"
"0x1b6558"

"0x1b6558"
"0x1b7d68"

这里定义了两个变量,当把b1直接复制给b2时采用浅拷贝,两个变量的数据地址相同。修改b2的内容时,采用深拷贝。

2.信号槽中的隐式共享

#include <QCoreApplication>
#include <QDebug>

class Test : public QObject {
    Q_OBJECT
public:
    void received(QByteArray byte) {
        qDebug() << Q_FUNC_INFO << "0x" + QString::number(reinterpret_cast<qintptr>(byte.constData()),16);
        byte = "x";
        qDebug() << Q_FUNC_INFO << "0x" + QString::number(reinterpret_cast<qintptr>(byte.constData()),16);
    }

signals:
    void sigByte(QByteArray byte);
};

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

    QByteArray b1 = "hello world";
    qDebug() << Q_FUNC_INFO << "0x" + QString::number(reinterpret_cast<qintptr>(b1.constData()),16);

    Test t;
    QObject::connect(&t,&Test::sigByte,&t,&Test::received);

    emit t.sigByte(b1);

    return a.exec();
}

#include "main.moc"

输出:

int main(int, char**) "0xf66558"
void Test::received(QByteArray) "0xf66558"
void Test::received(QByteArray) "0xf67df8"

同理信号槽中也是可以使用隐式共享的,其效果也是一样的。所以根本不用担心信号槽中传输大量数据下的效率问题。

3.多线程中信号槽的隐式共享

#include <QCoreApplication>
#include <QDebug>
#include <QThread>

class Test : public QObject {
    Q_OBJECT
public:
    void received(QByteArray byte) {
        qDebug() << QThread::currentThread() << Q_FUNC_INFO << "0x" + QString::number(reinterpret_cast<qintptr>(byte.constData()),16);
        byte = "x";
        qDebug() << QThread::currentThread() << Q_FUNC_INFO << "0x" + QString::number(reinterpret_cast<qintptr>(byte.constData()),16);
    }

signals:
    void sigByte(QByteArray byte);
};

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

    QByteArray b1 = "hello world";
    qDebug() << QThread::currentThread() << Q_FUNC_INFO << "0x" + QString::number(reinterpret_cast<qintptr>(b1.constData()),16);

    Test t;
    QObject::connect(&t,&Test::sigByte,&t,&Test::received);

    QThread th;
    t.moveToThread(&th);
    th.start();

    emit t.sigByte(b1);

    return a.exec();
}

#include "main.moc"

输出:

QThread(0xdd5ff0) int main(int, char**) "0xdd6558"
QThread(0x69fd60) void Test::received(QByteArray) "0xdd6558"
QThread(0x69fd60) void Test::received(QByteArray) "0x2593a48"

可以看到多线程中信号槽的数据传递也是支持隐式共享的。

4.结论

无论是多线程还是单线程中信号槽的数据传递都是支持隐式共享的,所以也不用担心大数据下的效率问题。
不过笔者这里只试验了QByteArray,未对其它数据结构验证,使用时请先查看Qt官方手册或自行测试。
建议在不需要进行数据更改的地方使用常引用const QByteArray&的方式传递,这样在信号槽的直接连接时构造临时变量的开销也可以省掉。
多线程中也可以使用常引用的方式传递,因为是异步通信,Qt会在信号传递时生成临时变量,不过内部数据依然是浅拷贝不需要担心。在数据没有被任何变量引用时进行析构。

  • 8
    点赞
  • 39
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Qt信号机制是Qt框架中的重要特性之一,它为对象之间的通信提供了一种灵活方便的机制。其优点和缺点如下: 优点: 1. 低耦合性:信号机制通过解耦发送者和接收者之间的直接调用,使得它们可以独立于彼此进行修改和维护,从而提高了代码的可维护性和扩展性。 2. 灵活性:信号机制可以在一个信号被触发时,同时向多个函数传递相应的参数,并且支持多对多的连接方式,提供了更大的灵活性。 3. 跨线程通信:由于Qt信号机制对线程的支持,可以轻松地进行跨线程通信,实现了线程之间的交互和数据共享。 缺点: 1. 运行效率:由于信号机制是基于动态连接的,相比于直接函数调用,会带来略微的性能损失。尤其在信号参数较多的情况下,可能会造成一定的性能影响。 2. 初始学习成本:对于初学者来说,掌握信号机制需要一定的时间和学习成本。理解信号的概念以及不同的连接方式和语法,可能需要一段时间才能熟练地使用。 3. 调试困难:信号机制会使代码的执行流程变得不太直观,尤其是涉及多个对象之间的信号连接时,可能会增加代码的调试难度。 总的来说,Qt信号机制的优点在于低耦合性、灵活性和跨线程通信的能力,但也存在一定的运行效率损失和学习成本高的缺点。根据具体情况,开发人员可以根据需求选择是否使用信号机制。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值