qt creator原始碼全方面分析(4-5)
阿新 • • 發佈:2020-05-10
[TOC]
# Qt中的字串
Qt中處理字串最常用的肯定是QString,但是在qt creator原始碼中出現了大量的QLatin1String。下面我們來介紹下區別。
## QLatinString
### 詳細介紹
我們首先來看[QLatinString](https://doc.qt.io/qt-5/qlatin1string.html)。類詳細介紹如下:
QString的許多成員函式都被過載以接受const char *而不是QString。 這包括複製建構函式,賦值運算子,比較運算子以及各種其他函式,例如insert(),replace()和indexOf()。 這些函式通常經過優化,以避免為const char *資料構造QString物件。 例如,假設str是QString,
QLatin1String類為US-ASCII/Latin-1編碼的字串文字提供了一個小型包裝器。
QString的許多成員函式都被過載以接受const char *引數而不是QString引數。 這包括複製建構函式,賦值運算子,比較運算子以及各種其他函式,例如insert(),replace()和indexOf()。 這些函式通常經過優化,以避免為const char *資料構造QString物件。 例如,假設str是QString,
```c++
if (str == "auto" || str == "extern"
|| str == "static" || str == "register") {
...
}
```
比下面的快很多
```c++
if (str == QString("auto") || str == QString("extern")
|| str == QString("static") || str == QString("register")) {
...
}
```
因為它不會構造四個臨時QString物件並進行字元資料的深拷貝。
定義QT_NO_CAST_FROM_ASCII巨集(如QString文件中所述)的應用程式無法訪問QString的const char * 介面API。為了提供一種指定常量Latin-1字串的有效方法,Qt提供了QLatin1String,它是const char *的非常薄的包裝。使用QLatin1String,上面的示例程式碼變為
```c++
if (str == QLatin1String("auto")
|| str == QLatin1String("extern")
|| str == QLatin1String("static")
|| str == QLatin1String("register") {
...
}
```
鍵入的時間稍長一些,但是它提供的功能與程式碼的第一個版本完全相同,並且比使用QString::fromLatin1()轉換Latin-1字串的速度更快。
多虧了QString(QLatin1String)建構函式,QLatin1String可以在需要QString的任何地方使用。 例如:
```c++
QLabel *label = new QLabel(QLatin1String("MOD"), this);
```
注意:如果你呼叫的函式,使用QLatin1String作為引數,實際上並未被過載來使用QLatin1String,而是進行QString的隱式轉換,並將觸發記憶體分配,而這是你通常使用QLatin1String首先要避免的情況。在這些情況下,使用QStringLiteral可能是更好的選擇。
### 原始碼
我們看下QLatin1String原始碼,進行了擷取,展現核心部分
```c++
class QLatin1String
{
public:
inline QLatin1String() : m_size(0), m_data(nullptr) {}
inline explicit QLatin1String(const char *s) : m_size(s ? int(strlen(s)) : 0), m_data(s) {}
private:
int m_size;
const char *m_data;
}
```
我們可以發現,真的是簡單的包裝,也沒有什麼深拷貝什麼的,只是把地址簡單的賦給了成員變數m_data。
### 小結
簡單說,QLatin1String就是對const char\*的簡單包裝,用在QT_NO_CAST_FROM_ASCII導致無法訪問QString的const char\*介面的地方。
## QStringLiteral(*str*)
QString這個大家都很熟悉了,我們也不過多介紹。這裡提一下[QStringLiteral](https://doc.qt.io/qt-5/qstring.html#QStringLiteral),大家可以在QString類介紹中找到。
### 詳細介紹
這是一個巨集,在編譯時從字串文字str中為QString生成資料。 在這種情況下,可以免費建立QString,並且將生成的字串資料儲存在已編譯目標檔案的只讀段中。
如果您的程式碼如下所示:
```c++
// hasAttribute takes a QString argument
if (node.hasAttribute("http-contents-length")) //...
```
然後這將建立一個臨時QString作為hasAttribute函式引數進行傳遞。 這可能會非常昂貴,因為它涉及記憶體分配以及將資料複製/轉換為QString的內部編碼。
通過使用QStringLiteral可以避免此成本:
```c++
if (node.hasAttribute(QStringLiteral(u"http-contents-length"))) //...
```
在這種情況下,QString的內部資料將在編譯時生成。在執行時不會發生任何轉換或分配。
使用QStringLiteral而不是用雙引號引起來的純C++字串文字,可以顯著加快根據編譯時已知的資料建立QString例項的速度。
注意:當將字串傳遞給具有過載QLatin1String引數的函式時,QLatin1String仍比QStringLiteral更有效,並且此過載避免了轉換為QString。例如,QString::operator ==()可以直接與QLatin1String進行比較:
```c++
if (attribute.name() == QLatin1String("http-contents-length")) //...
```
注意:某些編譯器編碼包含US-ASCII字符集以外字元的字串會有bug。在這種情況下,請確保在字串前加上`u`。否則是可選的。
### 原始碼
我們檢視巨集定義原始碼
```c++
t