为什么Qt的容器类不允许可移动但不可复制的元素类型?

15

Qt容器类 QList<T>, QVector<T>等要求其元素类型可被复制。自C++11起,STL容器需要其元素类型仅能够被复制或移动。为什么Qt容器不支持仅能移动的元素类型?


3
也许没有人提出/设计/实现这样的扩展?通常情况下,如果某事没被做,原因就是没有人做过。 - Kerrek SB
就像Kerrek所说的那样 :) 最终,是人们让事情成为可能。您可以随时为Qt5实现二进制兼容的放置,或者为Qt6创建全新的东西。获取Gerrit帐户,热身您的git,并开始编写代码 :) - Kuba hasn't forgotten Monica
1个回答

17

Qt bug #54685得到了Qt开发者的明确确认,因为Qt容器的隐式共享原则,移动只能类型不受支持也永远不会被支持。

当你将一个Qt容器复制到另一个容器时,你并没有进行深拷贝 - 容器在内部共享它们的内容。仅当在容器上调用修改函数时,它才会分离,创建自己的内容本地副本。这使得Qt容器可以通过信号和槽(必须按值传递)传递,而不会导致性能下降。

当然,当包含的类型是移动只能类型时,这将是不可能的。以值方式传递容器(而不复制其内容)的能力对于Qt的元对象机制至关重要,因此我认为它无法重新设计。即使在可以通过引用传递移动只能容器的情况下,Qt API也依赖于隐式共享并按值传递容器,因此没有简单的解决方法。


直接连接的插槽在调用时不会进行复制。队列连接则会被复制多次,每个插槽都会复制一次(因此可能是0次或更多次),但这只是一个任意的选择。我们可以将所有内容放在一个引用计数容器中,并且如果类型可移动,则可以将它们全部移动。我已经盯着那段代码很长时间了,也许有一天我会开始着手修补它。 - Kuba hasn't forgotten Monica
1
显然,具有不可复制元素的容器本身就不能被复制。因此,没有必要进行隐式共享。但是,如果元素类型是可复制的,则容器仍然可以保持可复制性。因此,现有功能不会减少,并且信号和插槽仍然可以像以前一样工作。 - Ralph Tandetzky
1
@RalphTandetzky 的问题在于当前的 Qt API 和流程 依赖 隐式共享,并且即使可以通过引用传递没有隐式共享的容器,也会通过值传递容器。 - Angew is no longer proud of SO
@Angew 谢谢你的澄清。那很有道理。 - Ralph Tandetzky
我还不理解“当包含的类型是移动语义时,这当然是不可能的。”。这里的“This”是指“只有在调用容器上的修改函数时,它才会分离,创建其自己的内容本地副本”吗?在我看来,对于移动语义类型,永远不会出现需要分离的情况,因为在尝试复制的瞬间,将会出现编译时错误。 - Johannes Schaub - litb
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接