QT字符串高效拼接原理QStringBuilder

 

 

这一篇文章讨论QT框架中QT字符串是如何实现高效拼接的。

 

1. QStringBuilder实例与原理

 

QT字符串高效拼接例子

 

 

 

 

 

备注:

(a)上述代码仅仅在s2 = b1时一次性分配能够容纳所有字符串的内存。

(b)定义两个符号之一即可使用operator+实现高效字符串拼接。

QT_USE_FAST_OPERATOR_PLUS

QT_USE_QSTRINGBUILDER

 

QStringBuilder原理

QStringBuilder提升字符串拼接性能的原理是什么?

(1)QStringBuilder是一个模板, QStringBuilder<A, B>

(2)内部仅仅保存了构造时传入的各种类型的字符串的引用。

(3)模板参数又可以嵌套一个QStringBuilder

(4)最后需要获取拼接结果时,执行operator QString()类型转换。

在这个转换中先计算总的字符串长度,然后一次性分配内存,构造出符合长度要求的QString,最后将各个组成部分拷贝到这个字符串中。

(5)整个拼接过程只需要分配一次内存,构造一个QString字符串作为最终拼接结果。中间不构造任何临时字符串。

 

 

 

2. 自己实现字符串高效拼接

 

 目标

 

 

 

 

备注:

(a)重载operator%运算符时必须至少有一个参数是类类型或者枚举类型。

因此不能直接实现两个原始字符串的%运算。

 

 

可连接类型

 

 

 

 

备注:

(a)这个类型关注具体如何进行连接操作,以及连接之后应该有多大。

为什么这个类型看起来并没有任何关于如何进行连接操作以及连接之后应该有多大的函数或者属性定义呢?这个是默认通用版本,通用版本无法确定数据类型,当然也就无法确定这些关注点,针对具体类型的特化版本才能确定这些关注点。

 

类型选择类型

 

 

 

 

备注:

(a)这个类型关注两个类型连接之后的结果类型是什么类型。

 

 

字符串拼接类型

 

 

 

 

 

 

 

备注:

(a)这个类型相当于字符串连接的一个总控程序。

 

 

 

特化版本: ButianyunStringBuilder

思考:

问题:类模板的特化版本中的模板参数是否可以比通用版本的模板参数更多呢?

答案:显然是可以的。ButianyunConcatenable就是这么一个具体的实例。

 

 

 

 

思考

问题:

根据ButianyunConvertHelper的定义,AB连接后的新类型为A

为什么不直接在这里定义AConvertToType,而是搞出来ButianyunConvertHelper这个模板呢?

 

答案:

ButianyunConvertHelper的价值是什么? 核心价值在于特化版本可以根据AB的具体情况来定义AB哪一个类型作为新类型。 在ButianyunConcatenable中无需关注这个问题。 如果不定义这个模板,直接定义AConvertToType则为硬编码。

AB连接后的新类型的决定权较给了这个类型外部的ButianyunConvertHelper

ButianyunConcatenable关注如何连接这件事情本身,而ButianyunConvertHelper关注类型。 优点是简化了ButianyunConcatenable的代码。 因此本质是关注点分离的思想。

 

 

 

 

特化版本:QLatin1String

 

 

 

 

 

特化版本: 原始字符数组

 

 

 

字符串连接函数

 

 

 

 

 

运算符重载:operator%

 

 

 

 

备注:

(a)这个运算符重载相当于对外提供了一个简化版本的API接口。

 

 

3. 总结

 

如果自己按照QT框架中QStringBuilder原理实现了字符串高效拼接则对QStringBuilder就有了更深入的认识了,对一个概念和用法做到知其然知其所以然。本文前面介绍的ButianyunStringBuilder实现基本上是QT框架中QStringBuilder的源码实现的简化版本。理解了ButianyunStringBuilder源代码基本上就已经掌握了QStringBuilder的源代码。

这个代码中使用了一些C++模板编程技术。C++模板编程技术本质上是一种取舍权衡之道,使用编译时间换取运行时间,也就是代码编译时间可能多一点,程序运行时的性能可能高一点。QT框架源代码很多时候为了追求运行时期的性能而使用了C++模板编程技术,使得源代码看起来有一点晦涩难懂。因此必须熟练掌握C++模板编程技术才能更好的掌握QT框架源代码。对于QT框架为什么使用这种模板编程技术,个人理解可能是这样的:QT框架的最大的特点在于易用性,但是QT框架中的很多基础设施又不想损失运行时期性能,那么自然而然就使用C++模板编程技术;当然有得必有失,损失一点源代码的可读性也可以算是提升了一点阅读源代码的门槛也就是很正常的事情;另外对于熟练掌握C++模板编程技术的软件工程师而言可能也不算什么门槛。

如果想更好的掌握C++,可以多看一些优秀的大型框架的源代码。这些大型框架经过多年沉淀,往往有一些比较优秀的编程思想。个人理解,掌握一些最基本最本质的编程思想可能比掌握一些框架的模拟两可的概念或者一些表面的API用法更实在一些,收益也更大一些。这也是在探索和分析QT源代码的过程中产生的一点可能在一些大佬看起来可能不值得一提的一点个人想法。