Qt信号槽在异步连接时需要将参数进行复制吗?

cpp 复制代码
class Sender : public QObject
{
	Q_OBJECT
signals:
	// void testSignal(QString msg);        // #1
	// void testSignal(const QString& msg); // #2
};

如上所示,当testSignal连接的槽函数在另一个线程时,有必要将参数类型写为#1这样吗?

我们可以在moc文件中看到信号的实现:

cpp 复制代码
void Sender::testSignal(const QString & _t1)
{
    QMetaObject::activate<void>(this, &staticMetaObject, 1, nullptr, _t1);
}

而QMetaObject::activate的实现参考Qt6.11源代码可见:

cpp 复制代码
void QMetaObject::activate(QObject *sender, const QMetaObject *m, int local_signal_index,
                           void **argv)
{
    int signal_index = local_signal_index + QMetaObjectPrivate::signalOffset(m);

    if (Q_UNLIKELY(qt_signal_spy_callback_set.loadRelaxed()))
        doActivate<true>(sender, signal_index, argv);
    else
        doActivate<false>(sender, signal_index, argv);
}

template <bool callbacks_enabled>
void doActivate(QObject *sender, int signal_index, void **argv)
{
	...
    // determine if this connection should be sent immediately or
    // put into the event queue
    if ((c->connectionType == Qt::AutoConnection && !receiverInSameThread)
        || (c->connectionType == Qt::QueuedConnection)) {
        queued_activate(sender, signal_index, c, argv);
            continue;
	...
}

static void queued_activate(QObject *sender, int signal, QObjectPrivate::Connection *c, void **argv)
{
...
    auto ev = c->isSlotObject ?
        std::make_unique<QQueuedMetaCallEvent>(c->slotObj,
                                               sender, signal, nargs, argTypes.data(), argv) :
        std::make_unique<QQueuedMetaCallEvent>(c->method_offset, c->method_relative, c->callFunction,
                                               sender, signal, nargs, argTypes.data(), argv);
...
}

可见异步信号槽将信号包装成了QQueuedMetaCallEvent,而QQueuedMetaCallEvent的构造函数如下:

cpp 复制代码
QQueuedMetaCallEvent::QQueuedMetaCallEvent(ushort method_offset, ushort method_relative,
                                           QObjectPrivate::StaticMetaCallFunction callFunction,
                                           const QObject *sender, int signalId, int argCount,
                                           const QtPrivate::QMetaTypeInterface * const *argTypes,
                                           const void * const *argValues)
    : QMetaCallEvent(sender, signalId, {nullptr, nullptr, callFunction, argCount,
                     method_offset, method_relative}),
      prealloc_()
{
    copyArgValues(argCount, argTypes, argValues);
}

inline void QQueuedMetaCallEvent::copyArgValues(int argCount, const QtPrivate::QMetaTypeInterface * const *argTypes,
                                                const void * const *argValues)
{
    allocArgs();
    void **args = d.args_;
    QMetaType *types = reinterpret_cast<QMetaType *>(d.args_ + d.nargs_);
    int inplaceIndex = 0;

    if (argCount) {
        types[0] = QMetaType(); // return type
        args[0] = nullptr; // return value pointer
    }
    // no return value

    for (int n = 1; n < argCount; ++n) {
        types[n] = QMetaType(argTypes[n]);
        if (typeFitsInPlace(types[n]) && inplaceIndex < InplaceValuesCapacity) {
            // Copy-construct in place
            void *where = &valuesPrealloc_[inplaceIndex++].storage;
            types[n].construct(where, argValues[n]);
            args[n] = where;
        } else {
            // Allocate and copy-construct
            args[n] = types[n].create(argValues[n]);
        }
    }
}

可见QQueuedMetaCallEvent将参数复制了一份,所以信号参数使用QString而不使用const QString&是没有必要的,反而增加了开销,而QQueuedMetaCallEvent已经将参数复制了一份,由事件循环系统将QQueuedMetaCallEvent派发到槽函数所在的线程后,也就相当于槽函数所在线程的本线程调用,槽函数参数也应当使用const QString& 而不是使用QString复制。

相关推荐
临床数据科学和人工智能兴趣组2 小时前
在R语言中, 使用 as.factor() 函数转换数值型变量
开发语言·r语言
andyweike5 小时前
php笔记
开发语言·笔记·php
Circ.6 小时前
Python 调试 Litellm 本地大模型接口:模型列表与对话接口实操踩坑记录
开发语言·python
现任明教教主~8 小时前
Thinkphp站群蜘蛛池SaaS系统YanyvSEO含多用户/积分/六大引擎计费/易支付对接
java·开发语言·spring
Zhou1411368 小时前
SpringSecurity_02_授权与高级功能
开发语言·python
码匠许师傅9 小时前
【C++三方组件】cpp-httplib:一个头文件起 HTTP 服务
开发语言·c++·http
小小小小钰儿10 小时前
1.5-Python网络编程
开发语言·网络·python·web安全·计算机·网络安全
hiahiahia12310 小时前
实现完整 Tool Dispatcher
开发语言·前端