是否可能,如果是这样,我怎样才能在Qt中创建一个信号/槽,它是对shared_ptr的const引用?我想要一个看起来像这样的信号:
void signal( shared_ptr<SomeClass> const & )
我知道如何在没有常量引用的情况下执行此操作,这只是类型shared_ptr<SomeClass>
,但出于效率原因,我想避免复制。引用类型的相同语法不起作用:
Q_DECLARE_METATYPE(shared_ptr<SomeClass> const &)
qRegisterMetaType<shared_ptr<SomeClass> const&>();
许多标准API都有QString const &
所以我认为它基本上是可行的,我只是无法弄清楚语法。
**性能的最大问题不是复制时间,而是当对象被复制到每个接收器时互斥锁定/解锁的数量 - 有很多。当多个线程使用该对象时,这会引起明显的减速/瓶颈。如果shared_ptr实际上只是使用原子操作,这个成本也是微不足道的,那么关于信号中const引用的一般问题仍然存在。*
答案 0 :(得分:7)
到目前为止,我发现我可以这样做:
Q_DECLARE_METATYPE(shared_ptr<SomeClass>)
qRegisterMetaType<shared_ptr<SomeClass> >();
qRegisterMetaType<shared_ptr<SomeClass> >("std::shared_ptr<SomeClass>const&");
我正在尝试验证这是否真的有效。这里的文档不清楚实际发生了什么。似乎信号/槽中的const引用类型将被编组为普通shared_ptr<SomeClass>
,这在这里完全没问题。有一些保证,这应该是这样的,但是很好。
我觉得简单的shared_ptr<SomeClass>
版本就是所有需要的,而boost
命名空间正在干扰信号。第二个版本似乎只是在全局命名空间中注册信号以便于使用。
我可以通过测试确认,const &
部分在排队连接中完全被忽略。每个连接的槽都获得该对象的新副本。这非常不幸。 :(
进一步的测试显示&
用于插槽,但是以不寻常的方式。仍然为排队连接创建对象的副本,但如果不使用引用,则将为该调用创建另一个副本。
因此,虽然每个connect
最终都会复制排队连接的数据,但引用仍然有点帮助。而且如果你确实有一些本地发送的信号(相同的线程),你可以避免更多的复制。
答案 1 :(得分:2)
根据此问题Argument type for Qt signal and slot, does const reference qualifiers matters?中的一个答案,对于排队连接,无论您如何连接信号和插槽,都会复制该对象。
由于您使用多个线程,因此连接已排队。如果您担心互斥成本,请尝试直接使用SomeClass *。