C++0x(C++11)新特性點(diǎn)評(píng)
白楊
http://
C++11 在不久之前已獲通過,它對(duì) C++03 的擴(kuò)充主要體現(xiàn)在核心語言和標(biāo)準(zhǔn)庫兩個(gè)方面,。作為《C++編碼規(guī)范與指導(dǎo)》中的一個(gè)小節(jié),,本文主要討論 C++11
中,新特性所帶來的變化,。
說明
右值引用(Rvalue reference,,T&&)解決了了左值引用(T&)無法傳遞臨時(shí)對(duì)象和常引用
(const T&)傳遞的對(duì)象只讀的問題,。右值引用允許傳遞一個(gè)可變更的臨時(shí)對(duì)象引用,主要用于配合移動(dòng)構(gòu)造,。 移動(dòng)構(gòu)造(move
constructor)使用移動(dòng)而非復(fù)制語義完成構(gòu)造過程,,主要用于解決從函數(shù)返回值時(shí)的大量深拷貝開銷,。使用右值引用和移動(dòng)構(gòu)造,,在按值傳遞和返回臨時(shí)對(duì)象時(shí),即可免去不必要的內(nèi)存分配和數(shù)據(jù)拷貝開銷,。
|
優(yōu)點(diǎn)
- 在特定情況下,,可實(shí)現(xiàn)內(nèi)存零拷貝,從而大大提高執(zhí)行效率,。
|
缺點(diǎn)
-
進(jìn)一步復(fù)雜化了對(duì)象傳遞的語義,。可想而知,,復(fù)合使用了傳址(指針,、引用、右值引用,,和它們的各種常量變體)以及傳值等各種對(duì)象傳遞方法的代碼,,其學(xué)習(xí)和維護(hù)成本都將較高。并且無論對(duì)其使用者還是實(shí)現(xiàn)者來說,,都比較容易產(chǎn)生
bug,。
- 需要為每個(gè)對(duì)象考慮多實(shí)現(xiàn)一種新的構(gòu)造方法。
- 在傳統(tǒng)的 C++03
代碼中,,通過智能指針等手段完全可以實(shí)現(xiàn)同樣的零拷貝,。若使用了帶有引用計(jì)數(shù)/寫時(shí)拷貝等特性的代理實(shí)現(xiàn),還能夠達(dá)到更好的零拷貝效果和更優(yōu)的性能。
- 通過智能指針等手段達(dá)到零拷貝的目的,,其方便性和易用性至少能夠與右值引用+移動(dòng)構(gòu)造相當(dāng),。
|
總結(jié)
只有在實(shí)現(xiàn)標(biāo)準(zhǔn)庫等某些必須返回值(而不能返回智能指針等句柄對(duì)象,也不能返回引用)的場合,,才考慮使用右值引用+移動(dòng)構(gòu)造方案,。其它情況下,智能指針或代理類通常是更好的選擇,。 |
|
說明
constexpr 主要用于修飾函數(shù)返回值,,表明該函數(shù)的返回值是編譯時(shí)已知的,意即:此函數(shù)內(nèi)僅包含一條形如“return
常量表達(dá)式;”這樣的語句,。constexpr 同樣也可以用來修飾對(duì)象,,如果用它來修飾用戶自定義類型,則用戶需要為該類型配備
constexpr 構(gòu)造函數(shù),,該構(gòu)造函數(shù)同樣僅允許使用編譯時(shí)已知的常量完成成員初始化,。 |
優(yōu)點(diǎn)
- 比內(nèi)聯(lián)還讓函數(shù)像宏。
|
缺點(diǎn)
總結(jié)
|
說明
POD(Plain Old Data)類型指那些布局與 C struct 兼容的用戶自定義類型。C++03 中對(duì) POD
類型的定義過于嚴(yán)苛,,在新標(biāo)準(zhǔn)中,,基本上,只要一個(gè)類不使用虛表和虛基類,;只使用默認(rèn)的構(gòu)造和析構(gòu)函數(shù),,并且其所有基類和成員也都如此的話,這個(gè)類的布局就是
POD 兼容的,。新標(biāo)準(zhǔn)取消了所有成員都必須是 public 訪問權(quán)限等沒有意義的限制條件,。 |
優(yōu)點(diǎn)
缺點(diǎn)
總結(jié)
事實(shí)上,,貌似從 C++ 誕生開始,廣大編譯器廠商就一直在使用上述放松標(biāo)準(zhǔn)了,。因此這一改動(dòng)只不過是順應(yīng)事實(shí)之舉,,對(duì)現(xiàn)有
C++ 程序員來說沒有任何影響。 |
|
說明
通過使用 extern
來修飾一個(gè)模板類,,告知編譯器該模板無需在當(dāng)前編譯單元內(nèi)實(shí)例化(必要的實(shí)例化已在其它編譯單元內(nèi)進(jìn)行),。 |
優(yōu)點(diǎn)
- 提供對(duì)于程序員來說,更明確,,與類型實(shí)例化(外部變量和對(duì)象定義)看上去更相似的模板顯式實(shí)例化方式,。
|
缺點(diǎn)
總結(jié)
大部分近代 C++
編譯器都已支持模板的顯式實(shí)例化。甚至不少編譯也早已允許在模板顯式實(shí)例化語句前面加個(gè)“extern”修飾詞了,。因此跟上一條一樣,,這也是屬于“先上車后補(bǔ)票”的勾當(dāng)。 |
|
說明
允許非 POD 容器類型通過初始化列表完成構(gòu)造,。 |
優(yōu)點(diǎn)
- 對(duì)于很多容器類型來說(比如:std:vector),,可大大方便其創(chuàng)建過程。
|
缺點(diǎn)
總結(jié)
好用的功能,,很適合經(jīng)常需要通過初始化列表來構(gòu)造容器對(duì)象的場合。 |
|
說明
無論是 POD 還是非 POD 類型都可以使用 obj = { ... } 的方式來進(jìn)行初始化,。對(duì)于非 POD 類型 {
... } 將自動(dòng)匹配和調(diào)用構(gòu)造函數(shù),。因此,,構(gòu)造函數(shù) T(x, y) 現(xiàn)在也可以寫成:T{x, y},、T var{x, y}
等,。在需要返回一個(gè) T 類型對(duì)象時(shí),甚至可以直接寫:“return {x, y};” |
優(yōu)點(diǎn)
- 一致的構(gòu)造方式便于編譯器和輔助工具完成語法解析,。
- 可以靈活地構(gòu)造和創(chuàng)建對(duì)象,。
|
缺點(diǎn)
- 濫用類似“return {x, y};”形式的自動(dòng)類型推斷很容易降低代碼易讀性和可維護(hù)性。
|
總結(jié)
|
說明
在 C++11 中,,auto
關(guān)鍵字的語義有所更改,從原來的聲明一個(gè)存活于當(dāng)前調(diào)用棧上的自動(dòng)變量,,轉(zhuǎn)變成了通過表達(dá)式的右值來自動(dòng)推斷左值的類型,。decltype
關(guān)鍵字則用于判斷指定表達(dá)式的類型,。 |
優(yōu)點(diǎn)
- 在定義模板,,或需要獲得 Lambda 表達(dá)式等匿名對(duì)象的類型時(shí),可提供方便,。
|
缺點(diǎn)
- 在模板中,,應(yīng)只在類型參數(shù)未知或很難獲得的時(shí)候才應(yīng)考慮使用上述機(jī)制。否則很容易極大地降低代碼易讀性和可維護(hù)性,。
- 類似地,,在普通代碼中,只應(yīng)在操作匿名類型對(duì)象時(shí),,才使用上述機(jī)制,。
- 雖然在 C++03 中,auto
關(guān)鍵字很少用到,。但也不可避免的帶來了兼容性問題——很少用到畢竟不等于完全沒用到,。
|
總結(jié)
應(yīng)僅在“被逼無奈”時(shí)使用,。 |
|
說明
沒啥好多說的,就是現(xiàn)如今已快爛大街的 foreach 類操作了,。對(duì)一些特殊容器和大部分守規(guī)矩(支持迭代子和
begin(),、end() 調(diào)用)的容器類型都有效。 |
優(yōu)點(diǎn)
缺點(diǎn)
總結(jié)
隨大流的 for 語句便捷寫法。沒有它日子也能過,,有了確實(shí)會(huì)方便些,,但也程度有限。 |
|
說明
可在表達(dá)式中定義一個(gè)匿名函數(shù)對(duì)象,,并返回它的實(shí)例,。對(duì)閉包(closure)的簡單解釋:一段可調(diào)用的代碼加上它執(zhí)行時(shí)所依賴的上下文。在
C++11 中,,閉包也是通過匿名函數(shù)對(duì)象的自動(dòng)生成來實(shí)現(xiàn)的,,例子:
std::vector<int> some_list;
int total = 0;
int value = 5;
std::for_each(some_list.begin(), some_list.end(), [&, value, this](int x) {
total += x * value * this->some_func();
});
|
相當(dāng)于:
class FOUnnamed {
private:
int& m_rnTotal;
int m_nValue;
CEnv* m_pEnv;
public:
FOUnnamed(int& total, int value, CEnv* this)
: m_rnTotal(total), m_nValue(value), m_pEnv(this)
{}
void operator()(int x)
{
m_rnTotal += x * m_nValue * m_pEnv->some_func();
}
};
std::vector<int> some_list;
int total = 0;
int value = 5;
FOUnnamed foPred(total, value, this);
std::for_each(some_list.begin(), some_list.end(), foPred);
|
因此可以認(rèn)為 lambda 表達(dá)式和閉包是一種生成匿名函數(shù)對(duì)象的快捷方式。 |
優(yōu)點(diǎn)
缺點(diǎn)
- 僅適用于封裝只有幾行代碼的簡單函數(shù)對(duì)象。如果濫用則很容易極大地降低代碼易讀性和可維護(hù)性,。
|
總結(jié)
經(jīng)典的特性,,如果使用恰當(dāng),能發(fā)揮強(qiáng)大的威力,。 |
|
說明
類似 lambda 表達(dá)式中的返回值定義方式,,模板和普通函數(shù)也可以使用類似的語法指定返回值,例如:
template<class Lhs, class Rhs>
auto adding_func(const Lhs &lhs, const Rhs &rhs) ->
decltype(lhs+rhs) {return lhs + rhs;} |
顯而易見,,這種語法主要用來幫助完成模板定義時(shí)的類型推斷——在上例中,,由于用來推斷返回類型的“l(fā)hs”和“rhs”在“adding_func(...)”之前還未定義,,因此必須將返回值類型定義延遲到參數(shù)列表之后。
應(yīng)注意到,,使用這種后置語法時(shí),,函數(shù)原來指定返回值類型的位置必須記做“auto”。 |
優(yōu)點(diǎn)
缺點(diǎn)
- 如果濫用則容易降低代碼易讀性和可維護(hù)性,。
|
總結(jié)
要么在整個(gè)項(xiàng)目中一致地使用,要么僅作為一種解決特定問題的手段,,在“被逼無奈”時(shí)才使用,。 |
|
說明
在 C++11
中,一個(gè)構(gòu)造函數(shù)可以調(diào)用該類中的其它構(gòu)造函數(shù)來完成部分初始化任務(wù)(委托),。聲明成員時(shí)可以直接指定默認(rèn)初始值,,例如:
class CSomeType {
int m_nNumber;
int m_nValue = 10;
public:
CSomeType(int new_number) : m_nNumber(new_number) {}
CSomeType() : CSomeType(42) {}
}; |
|
優(yōu)點(diǎn)
- 可在一定程度上簡化初始化相關(guān)代碼。
- 比起將構(gòu)造的公共部分封裝為一個(gè)私有方法供所有構(gòu)造函數(shù)調(diào)用,,委托更便于編譯器實(shí)現(xiàn)一些優(yōu)化,。
|
缺點(diǎn)
- 在 C++03
中,如果多個(gè)構(gòu)造函數(shù)需要使用同一段初始化代碼,,亦可將這段代碼封裝為一個(gè)私有方法供所有構(gòu)造方法調(diào)用,。
- 委托的加入改變了構(gòu)造的語義:C++03
中,當(dāng)一個(gè)對(duì)象的構(gòu)造函數(shù)返回時(shí),,該對(duì)象構(gòu)造完成,;而在新語義中,僅當(dāng)一個(gè)對(duì)象的所有構(gòu)造函數(shù)調(diào)用都返回后,,才表明該對(duì)象構(gòu)造完成,,使得對(duì)象構(gòu)造過程被進(jìn)一步地復(fù)雜化。
-
類似地,,基類和成員的構(gòu)造語義也被相應(yīng)地復(fù)雜化:僅當(dāng)基類中的所有構(gòu)造函數(shù)調(diào)用均返回時(shí),,派生類成員才開始構(gòu)造;當(dāng)成員中的所有構(gòu)造函數(shù)均返回后,,派生類才開始構(gòu)造……
|
總結(jié)
利大于弊,,值得一試,。但要搞清楚新的語義,,還要考慮好構(gòu)造函數(shù)中的異常拋出與處理方式。 |
|
說明
override
修飾符用于標(biāo)識(shí)指定的虛方法重載了基類中的同名虛方法——而不是定義一個(gè)新的同名虛方法(比如僅參數(shù)列表不同的虛方法),。該修飾符導(dǎo)致編譯時(shí)的嚴(yán)格檢查,,避免因?yàn)楹瘮?shù)簽名不同而重載失敗。
final 修飾符可用于修飾類或方法,。在修飾類時(shí),,它表示指定類是一個(gè) concrete 類——不能再作為基類而被其它類繼承,。
將
final 修飾符作用于方法時(shí),表示此虛方法已經(jīng)是最終實(shí)現(xiàn),,任何在派生類中重載這個(gè)方法的企圖都將引發(fā)一個(gè)編譯錯(cuò)誤,。 |
優(yōu)點(diǎn)
-
定義和派生抽象類的利器,可在編譯時(shí)發(fā)現(xiàn)諸如:修改了基類中某虛方法的參數(shù)列表后,,忘記在其派生類中做出相應(yīng)修改等各類相關(guān)錯(cuò)誤,。
- 使得類和虛函數(shù)定義的語義更清晰,有利于增強(qiáng)可讀性,。
- 為編譯器提供了更多的優(yōu)化線索,。
- override 和 final
只是修飾符,不是關(guān)鍵字,。它們除了在特定上下文中有特別含義外,,仍然可以作為合法的標(biāo)識(shí)符使用。
|
缺點(diǎn)
總結(jié)
|
說明
C++11 中定義了語言級(jí)的 NULL 指針常量:nullptr。 |
優(yōu)點(diǎn)
- 比起我們自定的“NULL”宏來說,,nullptr 常量更利于函數(shù)重載,。
|
缺點(diǎn)
總結(jié)
無論是 NULL 還是 nullptr,,都應(yīng)盡可能一致地使用(盡量避免混用),。 |
|
說明
C++11 通過“enum class
...”的語法為枚舉提供了強(qiáng)類型支持,同時(shí)還允許用戶指定枚舉的具體類型,,如:16位無符號(hào)整形,;32位整形;64位整形等等,。 |
優(yōu)點(diǎn)
- 強(qiáng)類型檢查杜絕了不同枚舉類型之間的比較或枚舉與整形之間的比較,,能夠在編譯時(shí)發(fā)現(xiàn)更多錯(cuò)誤。
- 可指定枚舉的位寬大大方便了很多原來不方便使用枚舉的場合(例如:可以打破 32 位限制,、可以顯式強(qiáng)制保證 8
位尺寸等等),。
|
缺點(diǎn)
總結(jié)
|
說明
定義模板實(shí)例時(shí),,不再需要小心地在多個(gè)連續(xù)的大于號(hào)之間添加空格了。 |
優(yōu)點(diǎn)
- 不必再擔(dān)心模板定義中的“>>”被解析為右移操作,。
|
缺點(diǎn)
總結(jié)
早就該有的特性,這算是語言級(jí)的 bugfix,? |
|
說明
在 C++11 中,,explicit 修飾符已可應(yīng)用于類型轉(zhuǎn)換操作,,幫助編譯器更好地完成類型轉(zhuǎn)換和函數(shù)重載判定。 |
優(yōu)點(diǎn)
-
一個(gè)與轉(zhuǎn)換操作的類型嚴(yán)格匹配的場合可以自動(dòng)應(yīng)用顯式類型轉(zhuǎn)換,,這使得顯式類型轉(zhuǎn)換操作可以在不降低易用性的前提下,,提供更好的類型匹配。
|
缺點(diǎn)
總結(jié)
基本上也屬于是早就該有的特性,,相信很多程序員都試著寫過“explicit operator bool()”、“explicit
operator INT64()”之類的東東,。 |
|
說明
可以使用 using 語法來定義模板實(shí)例的別名,。效果跟 typedef 基本一樣。 |
優(yōu)點(diǎn)
缺點(diǎn)
- 官方的說法是 C++03 不允許通過 typedef 定義包含整形模板參數(shù)的實(shí)例,。例如:“typedef
CHandle< T, DestoryDeletor<T>, CAtomicINT32, NULL >
HT;”語句按照 C++03 標(biāo)準(zhǔn)來說是非法的(假設(shè)“NULL”被定義為 0)。using 變種主要就是用來解決這個(gè)問題的,。但實(shí)際上我已經(jīng)在各種版本的 GCC,、VC、Intel C 等編譯器上這么用了很多年啊很多年,。
因此可以認(rèn)為這個(gè)功能就等同于 typedef,。
|
總結(jié)
意思不大,繼續(xù)用 typedef 就好,。如果覺得 using 更別致,,那么就請一致地使用(盡量避免混用)。 |
|
說明
在 C++11 中 union 中已可包含部分非 POD 類型,,也可以給 union 定義構(gòu)造函數(shù)和方法了,。 |
優(yōu)點(diǎn)
- 放寬了 union 對(duì)部分非 POD 成員的限制無疑會(huì)使其更有用。
- 允許為其定義構(gòu)造和方法進(jìn)一步方便了使用,。
|
缺點(diǎn)
- 無論如何,,由于 union 的先天性質(zhì),還是很難讓其支持析構(gòu)方法吧,?
- 其先天性質(zhì)決定了,,一個(gè)復(fù)雜 union 結(jié)構(gòu)的可讀性和可維護(hù)性恐怕都不怎么樣。
|
總結(jié)
好用的特性,,但要注意適可而止,,不要把設(shè)計(jì)搞的太復(fù)雜。 |
|
說明
為模板方法提供了類似普通函數(shù)的可變數(shù)量參數(shù)(...)支持,。 |
優(yōu)點(diǎn)
- 可極大地方便一些特殊模板的構(gòu)建,,例如:用于實(shí)現(xiàn)智能指針模板類中的“operator->*()”(成員指針解引用)操作,以及一些類似于“printf”的模板方法,。
|
缺點(diǎn)
總結(jié)
|
說明
C++11 中新增了 char16_t 和 char32_t 兩中類型,,用以應(yīng)對(duì) wchar_t
位寬不確定的問題。又新增了 UTF-8(u8),、UTF-16(u)和
UTF-32(U)字符串字面值定義方法,。同時(shí)還新增了一種無需對(duì)引號(hào)(")和反斜杠(\)等特殊字符進(jìn)行換碼的裸字符串字面值定義方法(R),該方法還可以與前面提到的 UTF 字面值前綴結(jié)合使用(u8R, uR, UR),非常全面和實(shí)用,。 |
優(yōu)點(diǎn)
- 明確了 UTF-8,、UTF-16 和 UTF-32 字符類型及其字面值定義方法。
- 對(duì)于經(jīng)常要寫些 HTML/XML 或者正則表達(dá)式之類字面值的童鞋來說,,裸字符串定義方式可以免除換碼的煩惱,。聽上去沒啥,但是等 coding 的時(shí)候……那是誰用誰知道呀,。
|
缺點(diǎn)
- 和 wchar_t 及相關(guān)舊代碼的兼容是個(gè)問題,。
|
總結(jié)
|
說明
就像“1000ul”表示“值為 1000 的無符號(hào)長整數(shù)”字面值一樣,,C++11 允許用戶通過新的“operator
""”操作自定義字面值后綴解釋器,,例如:
CMyClass operator "" _mysuf(const
char* literal_string);
CMyClass iVar = 1234_mysuf; |
|
優(yōu)點(diǎn)
- 用戶可以方便地直接通過字面值來生成自定義類型的對(duì)象。
|
缺點(diǎn)
- 不當(dāng)使用將導(dǎo)致代碼的可讀性和可維護(hù)性急劇下降,。
|
總結(jié)
這涉及到 coding 時(shí)方便與閱讀/維護(hù)時(shí)方便之間的權(quán)衡,,應(yīng)慎用。 |
|
說明
新標(biāo)準(zhǔn)中,,“thread_local”存儲(chǔ)類可用來指定一個(gè) TLS,。 |
優(yōu)點(diǎn)
- C++11 中規(guī)定任何可以使用“static”存儲(chǔ)類的地方,都可以使用 thread_local,。也就是說,,可以用它來修飾帶有構(gòu)造、析構(gòu)方法的對(duì)象,,使得
TLS 用起來非常簡便,。
|
缺點(diǎn)
- 從 thread_local 語義到實(shí)際操作系統(tǒng) TLS Slot API 之間的封裝和映射可能帶來額外的運(yùn)行時(shí)開銷。
|
總結(jié)
好用的東東,。比起直接使用操作系統(tǒng)的 TLS Slot 雖然可能增加少許隱式的開銷,,但通常對(duì) TLS
存取也沒有太高的效率要求(當(dāng)然至少要比使用互斥量等鎖算法要高效才行)。 |
|
說明
C++11 中,,用戶可以通過“= default”后綴修飾符,,為每個(gè)類顯式指定默認(rèn)構(gòu)造函數(shù)。也可以通過“=
delete”后綴修飾構(gòu)造函數(shù)和賦值等操作(通常用來實(shí)現(xiàn)禁止復(fù)制的語義)。 |
優(yōu)點(diǎn)
- 能夠通過明確的方式顯式限定這些特殊方法有助于增強(qiáng)代碼的可讀性和可維護(hù)性,。
|
缺點(diǎn)
總結(jié)
是傳統(tǒng)的,通過將拷貝構(gòu)造和賦值操作聲明為 private 來禁止復(fù)制或類似做法的最佳替代品,。 |
|
說明
C++11 中新增了確保至少 64 bit 的 long long 類型,。 |
優(yōu)點(diǎn)
缺點(diǎn)
總結(jié)
還有什么可說的呢,?同樣是一個(gè)早就該有,而且各大編譯器早已支持的特性,。 |
|
說明
類似 assert,,但專為模板而生:不像 assert 在運(yùn)行時(shí)才檢查,static_assert 在模板實(shí)例化時(shí)執(zhí)行,。 |
優(yōu)點(diǎn)
- 可在實(shí)例化點(diǎn)對(duì)模板參數(shù)進(jìn)行校驗(yàn),。
|
缺點(diǎn)
總結(jié)
|
說明
允許 sizeof 操作直接作用于類的成員,,例如:“sizeof CMyClass::m_nValue”。 |
優(yōu)點(diǎn)
- 個(gè)別模板定義會(huì)變得方便一點(diǎn),。
|
缺點(diǎn)
總結(jié)
C++03 雖然不允許類似:“sizeof CMyClass::m_nValue”的寫法,但也允許 sizeof 作用與對(duì)象的成員,,例如:“CMyClass
iTest; return sizeof(iTest.a)”之類,。而且除了事先不知道類型的模板以外,還真沒什么地方需要這么用
sizeof 的,。 |
|
|
標(biāo)準(zhǔn)庫的變化大體可分為以下三種類型:
- 為適應(yīng)新的核心語言而做出的調(diào)整和改進(jìn),,比如:為容器實(shí)現(xiàn)基于右值引用的移動(dòng)語義構(gòu)造方法、為模板使用 decltype
和可變參數(shù),、新增 UTF-32(Windows)或 UTF-16(linux/un*x)字符串支持等等,。
- 為了支持或更好地配合核心語言而新增的特性,例如 tuple,、initializer_list 等等,。
- 新增加的功能。
- 給像散列表(std::unordered_set,、std::unordered_map……)之類早已爛大街的東東一個(gè)名分,,以慰其在天之靈。
以下,,我們僅針對(duì)上述第三種情況進(jìn)行選擇性討論:
說明
新的標(biāo)準(zhǔn)庫提供了對(duì)線程,、互斥量,、條件變量、原子量和內(nèi)存屏障(參考:多處理器環(huán)境和線程同步的高級(jí)話題)
的基本支持,。但顯然不足以應(yīng)付那些需要長期,、穩(wěn)定、高效運(yùn)行的 Deamon / Service 開發(fā)任務(wù),。 |
優(yōu)點(diǎn)
- 勉勉強(qiáng)強(qiáng)可以湊合用的線程開發(fā)環(huán)境,。
- 提供了比較完整的原子量操作接口,,甚至支持 Acquire / Release 語義的內(nèi)存屏障,。
|
缺點(diǎn)
- 僅提供最基本的線程操作,對(duì)線程的超時(shí)等待,、掛起/恢復(fù),、優(yōu)先級(jí)/調(diào)度算法切換/搶占式調(diào)度設(shè)置、處理器粘滯性(CPU
Affinity)/最佳處理器設(shè)置,、保留棧/提交棧尺寸設(shè)置,、時(shí)間片調(diào)度控制(如:放棄當(dāng)前時(shí)間片、強(qiáng)制切換到其它線程等),、以及線程對(duì)象自動(dòng)銷毀(fire
and forget 語義,,不只是 detach 模式)等重要特性缺乏足夠支持,難以支撐真實(shí)的使用環(huán)境,。僅提供一個(gè) native_handle()
方法將一切負(fù)擔(dān)扔給用戶無疑是一種很不負(fù)責(zé)任的表現(xiàn),,與 Stroustrup 在《The C++ Programming
Language》中再三強(qiáng)調(diào)的“標(biāo)準(zhǔn)庫要么就不提供一種特性,要么就完整地提供關(guān)于該特性的所有操作”之理念完全背道而馳,。
- 沒有提供獲取在線和配置處理器數(shù)量以及處理器分組情況(如:Package Node,、NUMA Node、SMT/HT
Unit)等重要信息的工具,。這些都是涉及到能否真正用好線程/線程池的關(guān)鍵信息,。
- 提供了好用的遞歸互斥量,這很好,。但是:
- 互斥量到底使用高效的 FUTEX / Critical Secion 還是低效的 kernel
實(shí)現(xiàn)完全交給了庫的作者決定,。
- 缺乏超時(shí)等待(超時(shí) Lock)操作。
- 缺乏自旋鎖(Spin lock)支持,。實(shí)測表明,,在多處理環(huán)境下,使用自旋鎖與 FUTEX
配合的方案,,可以將鎖效率提升幾十至數(shù)百倍,。
- 缺乏信號(hào)量支持,雖然可以通過互斥量和條件變量模擬信號(hào)量操作,,但這無疑會(huì)對(duì)性能產(chǎn)生較大的影響,。
- POSIX 標(biāo)準(zhǔn)規(guī)定,無論成功與否,條件變量的 wait 操作都不保證其 mutex
參數(shù)的狀態(tài),,其狀態(tài)需要在 wait 返回后由用戶自行判定,。不知道標(biāo)準(zhǔn)庫是在這方面是怎么定義的?
- 所有同步工具都僅提供了無名版本——不支持有名互斥量和有名條件變量,。
- 不支持線程池,,需要用戶自己搞定。而用戶要通過既有的工具實(shí)現(xiàn)支持超時(shí)等待,、掛起/恢復(fù),、優(yōu)先級(jí)/調(diào)度算法切換、處理器粘滯性(CPU
Affinity)等等特性的線程池模塊基本上是癡心妄想,。
- 不支持消息隊(duì)列,、不支持生產(chǎn)者/消費(fèi)者鎖、不支持讀者/寫者鎖,。順便提一下:對(duì)于這些較為復(fù)雜的鎖算法,,Spin
Lock/FUTEX/FUSEM 之類技巧對(duì)效率的提升就更為明顯,因?yàn)槊看紊湘i,、解鎖都要涉及多個(gè)同步對(duì)象的操作,。
|
總結(jié)
原子量操作的接口完整度頗高,算是整個(gè)線程庫中唯一讓人欣慰地方,。但是效率具體如何,,還要看各廠商標(biāo)準(zhǔn)庫的表現(xiàn)了。根據(jù)經(jīng)驗(yàn),,5
年內(nèi)各主流編譯器廠商貌似很難把一個(gè)新加入標(biāo)準(zhǔn)庫的組件優(yōu)化到接近最佳狀態(tài),。 至于原子量以外的其余部分……也算可供業(yè)余玩家賞玩一番,
廖解寂寞吧,。 |
|
說明
新的標(biāo)準(zhǔn)庫支持正則搜索和替換,。 |
優(yōu)點(diǎn)
- 正則是一個(gè)無比常用的功能,不支持都沒天理了,。
|
缺點(diǎn)
- 正則也是一個(gè)對(duì)效率很敏感的功能,,其效率跟底層正則引擎關(guān)系甚大。優(yōu)秀的正則引擎使用 DFA/NFA
和各種優(yōu)化算法提示匹配效率,。
- 如果標(biāo)準(zhǔn)庫只支持 POSIX BRE / ERE
標(biāo)準(zhǔn)的正則,,那無疑是不夠的。如果支持?jǐn)U展的語法,,標(biāo)準(zhǔn)中有沒有明確定義,?是 Vim 風(fēng)格?Perl 風(fēng)格,?還是 TCL
ARE 風(fēng)格,?
- 對(duì) Unicode 支持如何,,例如:字符類 “\d”或
“[:digit:]”能否匹配中文全角“123”以及中文字符“一二三壹貳叁”等等?這部分在 C++11
標(biāo)準(zhǔn)中有明確定義還是要看各廠商的心情,?
|
總結(jié)
如果要用于一個(gè)嚴(yán)肅項(xiàng)目的話,,那么在正式使用前還需考察一段時(shí)間,最起碼要搞清楚幾個(gè)主流廠商的支持程度和實(shí)現(xiàn)方式,。 |
|
說明
TR1 終于提供了支持引用計(jì)數(shù)的智能指針,。 |
優(yōu)點(diǎn)
缺點(diǎn)
- 雖可自定義銷毀策略,,但也使得每個(gè)智能指針對(duì)象中多了個(gè)一個(gè) deletor
成員,對(duì)于智能指針這種本身尺寸就很小的句柄類來說,,多一個(gè) deletor 成員是個(gè)大負(fù)擔(dān),。其實(shí)銷毀策略完全可以通過模板參數(shù)傳遞,,這樣不占用內(nèi)存空間和也沒有任何額外的運(yùn)行時(shí)開銷,。
-
強(qiáng)制使用原子量,無法自定義引用計(jì)數(shù)的類型——對(duì)于某些僅需要在單線程環(huán)境內(nèi)使用的智能指針,,使用普通的整形做引用計(jì)數(shù)即可,。這有時(shí)能節(jié)省大量開銷。
- 不支持引用計(jì)數(shù)操作(比如經(jīng)典的 AddRef / Release),、靜態(tài)語義和所有權(quán)轉(zhuǎn)換等高效操作,。
對(duì)于新手,屏蔽到這些高級(jí)操作有助于產(chǎn)出更穩(wěn)定的代碼,,但對(duì)于老手來說,,這些操作可以帶來更高的效率和更多的用法。
- 不支持 NULL 值自定義——就好像不是所有對(duì)象都通過 delete
操作銷毀一樣,,也不是所有“指針”的無效值都是 nullptr,。例如:在使用智能指針來管理文件或 socket 句柄時(shí),其 deletor 應(yīng)該是 close
/ closesocket / CloseHandle 之類的調(diào)用,,而其“NULL”值應(yīng)該是無效句柄(通常是 -1,,而不是
NULL 對(duì)應(yīng)的 0 值。相反,,0 值一般是合法句柄),。
|
總結(jié)
應(yīng)付大多數(shù)情況足以,對(duì)效率和功能有特殊要求的情形下仍有不足,。 |
|
說明
新庫中提供了優(yōu)質(zhì)偽隨機(jī)數(shù)生成器,。 |
優(yōu)點(diǎn)
- 肯定比傳統(tǒng)的 rand 要優(yōu)質(zhì)。
|
缺點(diǎn)
- 到底有多優(yōu)質(zhì),?在 Windows 平臺(tái)上是使用 Crypto API 取種子的嗎,?在 un*x 平臺(tái)上是使用
/dev/random 或其變體取種子嗎,?隨機(jī)數(shù)生成的具體算法是什么?算法有多健壯,?算法效率如何,?一切都有待標(biāo)準(zhǔn)庫作者定奪?
|
總結(jié)
要真正用于密碼編碼學(xué)領(lǐng)域的話,,還需觀望,。要用在高速大批量生成隨機(jī)數(shù)的場合(比如:填充硬盤)也需觀望。 |
|
|
|