1. 程式人生 > >qt creator原始碼全方面分析(4-5)

qt creator原始碼全方面分析(4-5)

[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