当前位置: 首页 > news >正文

合肥宣传网站石家庄专业模板网站制作价格

合肥宣传网站,石家庄专业模板网站制作价格,苏州网站建设点一点,erp管理系统软件有哪些Qt 的信号signal的参数是否会在内部被拷贝? Qt 信号参数复制机制详解:Direct vs Queued 🧩 适配版本:Qt 5.15.2(源码路径基于 qtbase/src/corelib/kernel/qobject.cpp) 在这里插入图片描述 目录✨ 概览✅ …

Qt 的信号signal的参数是否会在内部被拷贝?


Qt 信号参数复制机制详解:Direct vs Queued 🧩

icon

适配版本:Qt 5.15.2(源码路径基于 qtbase/src/corelib/kernel/qobject.cpp

在这里插入图片描述

目录

    • ✨ 概览
    • ✅ 快速结论
    • 🔧 背后原理(源码走读)
      • 🧭 分派入口:`QMetaObject::activate`
      • 📦 QueuedConnection 如何复制参数
      • 🧵 BlockingQueuedConnection:直接传递 argv
    • 🧠 `const &` 会改变复制行为吗?
    • 🧰 自定义类型注意事项
    • 🚀 性能与生命周期建议
    • 🧪 小测试(自检题)
    • 📚 源码定位(Qt 5.15.2)
    • 🏁 结语


✨ 概览

Qt 信号发射到槽的过程中,参数到底有没有被复制,取决于连接类型:

  • DirectConnection:不复制参数,直接使用发射点准备的 argv 调用槽。
  • QueuedConnection:会复制每个参数的内容(使用 QMetaType::create),并在事件处理完毕后统一销毁(QMetaType::destroy)。
  • BlockingQueuedConnection:特殊的队列连接,直接传递 argv 指针,不做复制;通过信号量阻塞直到处理完成。

这与形参是否使用 const & 无关。只要进入队列(Queued),就需要参数拥有独立生命周期,因此需要复制;如果直接调用(Direct),就不需要复制。


✅ 快速结论

  • DirectConnection:不复制
    • 槽在发射线程立即执行,直接传入 argv
  • QueuedConnection:复制
    • 参数被封送到 QMetaCallEvent 内部,使用 QMetaType::create 创建副本,并由事件析构时销毁。
  • BlockingQueuedConnection:不复制(但阻塞)
    • 直接传递 argv,通过 QSemaphore 实现阻塞等待执行完成。
  • const & 修饰对复制与否无影响
    • 决策点在连接类型而非函数签名;Queued 需要自主管理生命周期,必然复制。

🔧 背后原理(源码走读)

🧭 分派入口:QMetaObject::activate

信号发射最终都会走到 QMetaObject::activate,在这里根据连接类型决定:直接调用还是投递事件。

关键分支(简化要点):

// 1) 需要队列:进入 queued_activate(复制参数并post事件)
if ((c->connectionType == Qt::AutoConnection && !receiverInSameThread)|| (c->connectionType == Qt::QueuedConnection)) {queued_activate(sender, signal_index, c, argv);continue;
}// 2) 阻塞队列:构造事件但直接传递 argv,不复制
} else if (c->connectionType == Qt::BlockingQueuedConnection) {QSemaphore semaphore;QMetaCallEvent *ev = c->isSlotObject ?new QMetaCallEvent(c->slotObj, sender, signal_index, argv, &semaphore) :new QMetaCallEvent(c->method_offset, c->method_relative, c->callFunction,sender, signal_index, argv, &semaphore);QCoreApplication::postEvent(receiver, ev);semaphore.acquire();continue;
}// 3) 直接连接:直接用 argv 调槽,不复制
if (c->isSlotObject) {obj->call(receiver, argv);
} else if (c->callFunction && c->method_offset <= receiver->metaObject()->methodOffset()) {callFunction(receiver, QMetaObject::InvokeMetaMethod, method_relative, argv);
} else {QMetaObject::metacall(receiver, QMetaObject::InvokeMetaMethod, method, argv);
}

📦 QueuedConnection 如何复制参数

当判定需要排队时,会调用 queued_activate。在此函数中:

  • 计算 nargs(含返回值槽位)
  • 创建 QMetaCallEvent,为其参数与类型数组分配空间
  • 逐一使用 QMetaType::create(type, argv[n]) 构造每个参数的副本

关键代码要点:

QMetaCallEvent *ev = c->isSlotObject ?new QMetaCallEvent(c->slotObj, sender, signal, nargs) :new QMetaCallEvent(c->method_offset, c->method_relative, c->callFunction, sender, signal, nargs);void **args = ev->args();
int *types = ev->types();// 参数类型填充(types[0] 为返回类型槽位,置0;args[0] 置nullptr)
for (int n = 1; n < nargs; ++n)types[n] = argumentTypes[n-1];// 复制每个参数到事件内部
for (int n = 1; n < nargs; ++n)args[n] = QMetaType::create(types[n], argv[n]);QCoreApplication::postEvent(c->receiver.loadRelaxed(), ev);

对应的释放逻辑在 QMetaCallEvent::~QMetaCallEvent()

for (int i = 0; i < d.nargs_; ++i) {if (typeIDs[i] && d.args_[i])QMetaType::destroy(typeIDs[i], d.args_[i]);
}

🧵 BlockingQueuedConnection:直接传递 argv

为阻塞队列连接提供的构造函数注释已明示“直接传递 args,不分配内存”:

// Used for blocking queued connections, just passes args through without allocating any memory.
QMetaCallEvent::QMetaCallEvent(..., void **args, QSemaphore *semaphore)

🧠 const & 会改变复制行为吗?

不会。是否复制只由“是否进入队列(Queued)”决定:

  • Direct/BlockingQueued:直接使用发射点 argv,不复制。
  • Queued:必须复制,确保跨线程/异步投递后的独立生命周期。

与形参是否 const T&TT&& 无关;Queued 的复制依据 QMetaType 可构造/销毁能力。


🧰 自定义类型注意事项

  • 传递到 QueuedConnection 的参数类型必须可通过 QMetaType 构造与销毁。
  • 若为自定义类型:
    • 使用 Q_DECLARE_METATYPE(T) 声明。
    • 在使用前注册:qRegisterMetaType<T>("T")
  • 指针类型特殊处理:如果参数名以 * 结尾,视作 QMetaType::VoidStar,不会复制对象本身,仅复制指针值。

🚀 性能与生命周期建议

  • 频繁高频的信号传递且无需跨线程,优先使用 DirectConnection(或默认 Auto 且同线程)。
  • 跨线程/异步场景下,QueuedConnection 安全但存在参数复制与事件分发开销。
  • 对体积较大的对象:
    • 优先传指针或 QSharedPointer<T>,避免大对象复制。
    • 若必须值传递,请确保类型的 QMetaType 构造/销毁开销可接受。

🧪 小测试(自检题)

  1. 同线程 AutoConnection 默认是什么行为?为什么?
  2. const QString& 作为信号参数,QueuedConnection 会复制吗?
  3. BlockingQueuedConnection 是否复制参数?它的额外语义是什么?

参考答案:

  • 1)等效 Direct,不复制;因为接收者与发送者同线程。
  • 2)会复制;Queued 必须复制与 const & 无关。
  • 3)不复制;但会阻塞发送线程直到槽执行完成。

📚 源码定位(Qt 5.15.2)

  • 连接类型分派与直接调用:
    • qtbase/src/corelib/kernel/qobject.cppQMetaObject::activatedoActivate
  • 队列封送与复制:
    • qtbase/src/corelib/kernel/qobject.cppqueued_activateQMetaCallEvent 构造/析构
  • 参数类型解析:
    • queuedConnectionTypes()(同文件顶部附近):处理 QMetaType id,指针类型→VoidStar

🏁 结语

Qt 的参数是否复制,核心看连接类型:Direct 不复制、Queued 一定复制、BlockingQueued 不复制但阻塞。掌握这一点,有助于做出正确的 API 设计与性能权衡,避免隐藏的生命周期问题与不必要的开销。

祝你写出更优雅高效的 Qt 信号/槽系统!🎉

http://www.dtcms.com/a/546909.html

相关文章:

  • 网站策划过程无锡网站建设外包
  • 南京网站建设网深圳西乡 网站建设
  • 滦南县建设局网站农场理财网站建设
  • 唐山网站制作企业回收手表的网站
  • 好消息:KMRE 安卓模拟器现可在Debian/GXDE使用
  • 主营网站开发焦作网站建设设计公司
  • 怎么买域名建网站宣传片制作方案
  • FLOW大纲
  • 缺乏版本控制规范会带来哪些灾难
  • 网站优化的方法与技巧如何做企业黄页网站
  • 企业网站开发框架广州企业500强名单
  • 网站域名需要每年续费做网站应该用什么配置的电脑
  • 深度学习中的两个不确定性
  • 上海网站推广珈维上海做网站哪个好
  • 淮安网站建设要多少钱网站建设软件app
  • 没有网站如何做天天联盟做网站运营需要学的东西
  • Windows开发,制作开发软件安装程序(二)
  • python2
  • 月饼网站建设广州黄埔建网站
  • 织梦如何制作静态网站模板3d全景网站怎么做
  • 开什么网站暴利企业网站内的问答模式怎么做
  • 威海网站建设whhl网站设计素养
  • 温州网站建设平台网站软件下载大全
  • 自贡企业网站学校信息门户网站建设
  • 网站策划方案详解苏州企业网站建设公司价格
  • 长沙企业网站建设收费施工企业管理制度
  • 西安网络公司网站建设12306网站制作
  • dede批量建站昆明哪个公司做网站建设最好
  • 公司建设门户网站的意义网站开发框架参考文献
  • 力扣410. 分割数组的最大值