为什么 Qt 不支持仅移动的 QList?

3
虽然已经有人问过为什么Qt的容器类不允许可移动但非可复制的元素类型,但我还是想再问一次。我看过了QtCore维护者Thiago的言论,他在链接的Stackoverflow问题的答案中提到:

永远不会实现。由于隐式共享,可复制性是强制要求。

我不理解这个说法:我理解可复制性是隐式共享的强制要求,但为什么对于一个非可复制的QList<T>来说,隐式共享是必须的?

QList已经具备移动构造函数和移动赋值运算符,因此我们可以假设从另一个临时QList<T>构造一个QList<T>将不会应用隐式共享,而是移动基础的d指针。在只复制/赋值临时/右值QList的情况下,什么情况下会出现隐式共享?


说到“Qt和为什么不”,一切都指向过去做出的决策与新范式的冲突。 - rubenvb
2个回答

1

所有的Qt容器类都是隐式共享的。这不是可以商量的事情。否则,如果一个通过值发出QList信号需要连接到多个插槽,你想怎么做呢?没有移动语义或者没有隐式共享,你会得到很多副本。有了移动语义,除了第一个插槽之外,其他插槽将得到一个空(好吧,未指定的移动自)列表。因此,在其API细节的其余部分中,隐式共享成为必需品,其中包含太多的按值传递,因为为什么不呢?反正一切都是隐式共享的。

总之,我认为Qt不想对任何容器的实现进行例外处理,例如使移动列表不隐式共享,而其他任何列表都会隐式共享。副作用的差异太大了。

还要注意的是,至少在读行间时,他们更倾向于使用std容器,尽管让它们出现在API中需要比任何人都喜欢的时间长...


但是当尝试发出一个移动类型(例如仅限移动的QList)时,它们可以只给出编译器错误。我已经可以编写一个仅限移动的类型并尝试发出其值,并希望能够获得错误消息(尚未尝试)。为什么他们需要为仅限移动列表制定例外呢?它们仍将被隐式共享,但永远不会需要隐式共享,因为永远不会执行或允许复制。但从他们在链接的错误报告中所写的内容来看,即使是仅限移动的QList也需要被隐式共享-我还需要理解为什么。 - Johannes Schaub - litb

0

可能是因为 QList 仅被标记为可重入,但不是线程安全的(定义)。

我没有查看源代码,但猜测维护线程安全 QList 的开销超过了支持普通用户的成本(当然这只是假借口 :P)。

当 T 是指针或引用时,修改列表中的对象可能意味着必须同步多个内存空间 - 这似乎超出了 Qt 框架的范围。我还可以想象,如果主线程中有某个工厂实例化对象,或者对象拥有对线程或回调的引用/指针时,这也会变得复杂。

也许不应该回答你的任何问题,但这篇文章比评论还长。


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