为什么 `QDateTime` 实现了隐式共享?

4

根据文档,隐式共享主要是为了提高性能(避免复制和自动更改时的复制)。

为什么对于表面上只需要很少字节的QDateTime类也实现了隐式共享?我认为堆分配和线程同步的引用计数更新成本远远超过了不复制几个字节所带来的小收益。

1个回答

2

简短回答:它更便宜。

详细回答:Qt是围绕PIMPL模式设计的。创建一个对象的真实副本意味着你必须为PIMPL分配新的堆并复制两个对象。特别是对于小对象,新的分配成本相当昂贵。为了解决这个问题,他们决定为许多甚至小的类实现写时复制。

Original Answer翻译成"最初的回答"


1
并非所有的Qt都使用PIMPL方式实现;两个微不足道但相关的反例是QDateQTime,它们是“常规”的类,其数据直接位于它们的private:部分中。那么QDateTime有何不同呢? - Matteo Italia
1
@MatteoItalia QDate和QTime都不试图处理时区,因此它们可以由一个单独的数字完全表示,而且没有任何真正的理由会改变这种情况,所以PIMPL是非常无用的,把它们放在堆栈上是更好的。 QDateTime处理时区会增加复杂性。此外,至少有一个QString用于存储时区名称,所以已经使用了堆分配,并且去除它并不是巨大的优化。 - Joseph Ireland
@JosephIreland QDateTime 包含一个 QTimeZone,但它本身是一个基于 QSharedDataPointer 的类,通常为空(因此没有需要分配的内存),或者是从其他地方共享的副本(并且是不可变的,所以你无法以任何方式分离它)。如果 QDateTime 不是 dptr-based 的话,就根本不会有任何堆分配。 - Matteo Italia
我唯一看到的问题是QTimeZone支持是有条件的,因此如果需要在Qt版本中编译的应用程序与提供它的库版本之间保持ABI兼容性,则对于QDateTime的PIMPL(可能包括QTimeZone,也可能不包括)可能会很有用。但是,反过来,添加一个虚拟的“QTimezone”版本将是微不足道的。 - Matteo Italia
@MatteoItalia 这是真的,但也有状态标志和夏令时信息,我想开发人员认为这足够复杂,需要使用 PIMPL。 - Joseph Ireland
看起来并没有帮助,阅读源代码后发现他们将很多实现锁定在序列化代码中,因此在这里使用PIMPL可能是一个错误。虽然很难抱怨,因为Qt在二进制兼容性方面非常出色,他们更关心的是这个而不是小的性能提升。 - Joseph Ireland

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