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源程式碼的過程中產生的一點可能在一些大佬看起來可能不值得一提的一點個人想法。