[轉載]QString 亂談(3)-Qt5與中文

 

原文地址http://blog.csdn.net/dbzhang800/article/details/7542672?reloadlinux

 

 

 

兩個月前,簡單寫過QTextCodec中的setCodecForTr等終於消失了 (Qt5) ,在Qt論壇上,很多用戶都對去掉這兩個函數表示特別的不瞭解。爲何會這樣?我想多少能說明很多用戶對C++中源碼字符集和執行字符集的不太瞭解,從而形成對這種函數的依賴或誤用。函數

今天,隨着Change QString's default codec to be UTF-8 進入Qt5的master分支,咱們總算能夠從新審視一下Qt的中文支持問題。編碼

20120516更新:建議閱讀QtCore模塊維護者Thiago Macieira 的文章 Source code must be UTF-8 and QString wants it 
spa

沒有了setCodecXXX的Qt5

  • Qt5假定的執行字符集是UTF8,再也不容許用戶擅自改動。這樣一來,Qt4中setCodecXXX的各類反作用再也不存在,並且中文問題更爲簡單。.net

 

QString s1 = "漢語";
QString s2("漢語");
QString s3 = tr("中文")
QString s4 = QStringLiteral("中文");//只要字符串不須要翻譯,請關注這個
QString s5 = QString::fromWCharArray(L"中文");
QString s6 = u8"中文";//C++11
QString s7 = tr(u8"中文")
...

全部這些在Qt5默認都會正常工做,惟一要求就是:確保你的C++的執行字符集(the execution character set)是UTF-8翻譯

各類寫法PK?

簡單不必定好

最簡單直接的用法,當屬:code

QString s1 = "漢語";
QString s2("漢語");
QString s6 = u8"中文";//C++11
...

這有什麼問題呢?blog

  • 定義宏QT_NO_CAST_FROM_ASCII以後,上述代碼沒法將經過編譯(對了,這個宏彷佛應該改個名字纔對,叫QT_NO_CAST_FROM_CSTRING會名副其實一些)utf-8

被誤用最多的

在Qt4中,QObject::tr()是被濫用(誤用)的函數之一:ci

QString s3 = tr("中文")
...

緣由:

  • 在Qt4,很多用戶被鋪天蓋地的setCodecForTr()所影響,進而靠它來解決中文問題。

它的用途是用來進行翻譯(I18N和L10N)的,若是你沒有這方面的需求,真的不必用它。(在Qt4中,我只注意到有2個大陸網友和1個日本網友有需求並真正進行過這方面的嘗試,那麼其餘應該算誤用吧?)

讓人困惑的wchar_t

剛開始接觸Qt和QString時,曾屢次想過,爲何不用wchar_t,爲何,...

QString s5 = QString::fromWCharArray(L"中文");

這個東西在Windows下真的頗有用:首先它是Windows系統API所用字符串,其次它和QString內部表示相同。可是因爲MSVC處於種種考慮,鼓勵你們使用TEXT/_T,反倒使你們對它比較陌生。

可是從C++標準來講,wchar_t畢竟不是char16_t,因此跨平臺性很差。在linux下,這行代碼須要utf32到utf16的轉換。

QStringLiteral

這是一個宏,一個蠻複雜的宏:

QString s4 = QStringLiteral("中文");

以前?

在介紹這個宏以前,咱們先看看下面寫法有什麼劣勢:

QString s1 = "漢語";
QString s2("漢語");
QString s3 = tr("中文")
QString s6 = u8"中文";//C++11
...

首先,2個漢字的字符串以UTF-8編碼的形式被編譯器放到了常量區。(至少佔7個字節吧?)

而後,程序運行時,構造QString實例,須要在堆上申請空間,存放utf16格式的相應字符串。

有沒有存在浪費?

方案

QString 內部是UTF16,若是C++編譯器在編譯期直接提供了UTF16的字符串,那麼咱們在QString內部直接保存也就夠了。這樣

  • 省掉存在兩份不一樣的拷貝(即相應的轉換,malloc的成本)
  • 對漢字來講,UTF16自己就是UTF8省空間

現實

目前,咱們尚未可靠的方式在C++使用UTF16的執行字符集(the execution character set)。

  • 儘管 L"..."(wchar_t*) 在Windows下是UTF16,可是不具有跨平臺性。
  • C++11能夠保證這一點,u"..."(char16_t),但主流編譯器還沒有提供完美支持。

這兩點,致使了QStringLiteral的複雜性

實現

源碼見 qtbase/src/corelib/tools/qstring.h

(代碼中使用宏、模板、lambda表達式,仍是至關複雜的,此處只摘片斷)

  • 若是編譯器支持char16_t,則直接使用

 

#define QT_UNICODE_LITERAL_II(str) u"" str
typedef char16_t qunicodechar;
...
  • 不然。若是在Windows平臺下,或者在其餘的wchar_t寬度爲2的環境下,使用wchar_t

 

#if defined(Q_CC_MSVC)
#    define QT_UNICODE_LITERAL_II(str) L##str
#else
#    define QT_UNICODE_LITERAL_II(str) L"" str
#endif
typedef wchar_t qunicodechar;
...
  • 不然。編譯器不支持,Qt做爲一個庫,確定也沒有辦法

 

# define QStringLiteral(str) QString::fromUtf8(str, sizeof(str) - 1)
相關文章
相關標籤/搜索