C++11

C++11，先前被稱作C++0x，即ISO/IEC 14882:2011，是C++程式語言的一個標準。它取代第二版標準ISO/IEC 14882:2003。ISO／IEC JTC1/SC22/WG21 C++標準委員會計劃在2010年8月之前完成對最終委員會草案的投票，以及於2011年3月召開的標準會議完成國際標準的最終草案。然而，WG21預期ISO將要花費六個月到一年的時間才能正式釋出新的C++標準。為了能夠如期完成，委員會決定致力於直至2006年為止的提案，忽略新的提案[1]。最終於2011年8月12日公佈，並於2011年9月出版。2012年2月28日的國際標準草案是最接近於C++11標準的草案，差異僅有編輯上的修正。像C++這樣的程式語言，透過一種演化的過程來發展其定義。這個過程不可避免地將引發與現有程式碼的相容問題，在C++的發展過程中偶爾會發生。不過根據比雅尼·斯特勞斯特魯普表示，新的標準將幾乎100%相容於現有標準。設計原則.C++的修訂包含核心語言以及標準程式庫。在發展新標準的每個機能上，委員會採取了幾個方向：關照初學者被認為是重要的，因為他們構成了計算機程式設計師的主體。也因為許多初學者不願擴充套件他們對C++的知識，只限於使用他們對C++專精的部分。此外，考慮到C++被廣泛的使用，即便是最有經驗的程式設計師在面對新的程式設計正規化時也會成為初學者。C++核心語言的擴充.C++委員會的主要作用之一是改善語言核心。核心語言將被大幅改善的領域包括多執行緒支援、泛型程式設計、統一的初始化，以及效能表現的加強。在此分成4個區塊來討論核心語言的特色以及變更：執行期表現強化、建構期表現強化、可用性強化，還有新的功能。某些特性可能會同時屬於多個區塊，但在此僅於其最具代表性的區塊描述。核心語言的執行期表現強化.以下的語言機能主要用來提升某些效能表現，像是記憶體或是速度上的表現。右值引用和move語意.在C++03及之前的標準，臨時物件。儘管如此，在某些情況下臨時物件仍然可能會被改變，但這種表現也被視為是一個有用的漏洞。C++11增加一個新的非常數引用，標記為codice_1。右值引用所繫結的臨時物件可以在該臨時物件被初始化之後做修改，這是為了允許move語意。C++03低效能問題的之一，就是在以傳值方式傳遞物件時隱式發生的耗時且不必要的深度複製。舉例而言，codice_2本質上是一個C-style陣列及其大小的封裝，如果一個codice_2的臨時物件是在函式內部或者函式返回時建立，要將其儲存就只能透過生成新的codice_2並且把該臨時物件所有的資料複製過去。然後該臨時物件會被析構，其使用的記憶體會被釋放。在C++11，把一個codice_5的右值引用作為引數codice_6的"move建構子"，可以把右值引數所繫結的codice_5內部的指向C-style陣列的指標複製給新的codice_5，然後把該指標置null。由於臨時變數不會被再次使用，所以不會有程式碼去訪問該null指標；又因為該指標為null，當該臨時物件超出作用域時曾經指向的內部C-style陣列所使用的記憶體不會被釋放。因此，該操作不僅無形中免去了深複製的開銷，而且還很安全。右值引用作為資料型別的引入，使得函式可以過載區分它的引數是值型別、傳統的左值引用還是右值引用。這讓除了標準庫的現有程式碼無須任何改動就能等到效能提升。一個返回codice_2的函式的返回型別無須為了呼叫move建構函式而顯式修改為codice_10，因為臨時物件自動作為右值。出於安全的考慮，推行了一些限制。具名的變數被認定為左值，即使它是被宣告為右值引用資料型別；為了獲得右值必須使用顯式型別轉換，如模板函式codice_13。右值引用所繫結的物件應該只在特定情境下被修改，主要用於move建構函式中。void test(int &amp;&amp; i)is_r_value(i); // i為具名變數，即使被宣告成右值引用型別，i作為實參表示式也不會被認定是右值表示式。is_r_value(std::move()取得右值。由於右值引用的語義特性以及對於左值引用方法中看到。constexpr – 泛化的常數表示式.C++本來就已具備常數表示式都要求必須是常數表示式。然而，常數表示式不能含有函式呼叫或是物件建構式。所以像是以下的例子是不合法的：int some_value[GetFive() + 7]；// 欲產生12個整數的陣列。不合法的C++寫法這在C++03中是不合法的，因為codice_15並不是常數表示式。C++03編譯器無從得知codice_16實際上在執行期是常數。理論上而言，這個函式可能會影響全域變數，或者呼叫其他的非執行期常數函式等。C++11引進關鍵字codice_17允許使用者保證函式或是物件建構式是編譯期常數。以上的例子可以被寫成像是下面這樣：int some_value[GetFive() + 7]；// 欲產生12個整數的陣列。合法的C++11寫法這使得編譯器能夠瞭解並去驗證codice_16是個編譯期常數。用codice_17修飾函式將限制函式的行為。首先，該函式的回返值型別不能為void。第二，函式的內容必須依照"return "expr""的形式。第三，在引數替換後，codice_20必須是個常數表示式。這些常數表示式只能夠呼叫其他被定義為codice_17的函式，或是其他常數表示式的資料變數。最後，有著這樣修飾符的函式直到在該編譯單元內被定義之前是不能夠被呼叫的。宣告為codice_17的函式也可以像其他函式一樣用於常量表達式以外的地方，此時不需要滿足後兩點。C++11之前，可以在常量表達式中使用的變數必須被宣告為codice_23，用常量表達式來初始化，並且必須是整型或列舉型別。C++11去除了變數必須是整型或列舉型別的限制，只要變數使用了codice_17關鍵字來定義：constexpr double earth_gravitational_acceleration = 9.8;constexpr double moon_gravitational_acceleration = earth_gravitational_acceleration / 6.0;這些變數都是隱式常量，必須使用常量表達式來初始化。為了讓使用者自定義型別。擁有codice_17建構函式的型別的複製建構函式通常也應該被定義為codice_17，以便該型別的物件以值傳遞的方式從codice_17函式返回。該類別的任何成員函式，像是複製建構式、運算子過載函式等等，只要他們符合常數表示式函式的定義，都可以被宣告成codice_17。使得編譯器能夠在編譯期進行類別的複製、對他們施行運算等等。常數表示式函式或建構式，可以以非常數表示式作為引數喚起。就如同codice_17整數字面值能夠指派給codice_32變數，codice_17函式也可以接受codice_32引數，其結果儲存於codice_32變數。codice_17關鍵字只有當表示式的成員都是codice_17，才允許編譯期常數性的可能。對POD定義的修正.在C++03中，一個類，而且可以被靜態初始化。但C++03標準嚴格限制了何種型別與C相容或可以被靜態初始化的，儘管並不存在技術原因導致編譯器無法處理。如果建立一個C++03 POD型別，然後為其新增一個非虛成員函式，這個型別就不再是POD型別了，從而無法被靜態初始化，也不再與C相容，儘管其記憶體佈局並沒有發生變化。C++11透過把POD概念劃分成兩個概念："平凡的"，放寬了關於POD的定義。一個平凡的型別可以被靜態初始化，意味著使用codice_40來複制資料是合法的，而無須使用複製建構函式。平凡的型別物件的生命週期開始於其儲存空間被分配時，而不是其建構函式完成時。使用模版類std::is_trivial::value來判斷資料型別是否為平凡型別一個平凡的類別或結構符合以下定義：一個符合標準佈局的類封裝成員的方式與C相容。使用模版類std::is_standard_layout::value來判斷型別是否是一個標準佈局型別。一個標準佈局的類別或結構符合以下定義：一個類、結構、聯合只有在其是平凡的、符合標準佈局，並且所有非靜態成員和基類都是POD時，才被視為POD。使用::value判斷T是不是POD型別透過劃分，使得放棄一個特性而不失去另一個成為可能。一個具有複雜的複製和move建構函式的類可能不是平凡的，但是它可能符合標準佈局，從而能與C程式互動。類似地，一個同時具有public和private資料成員的類不符合標準佈局，但它可以是平凡的，從而能夠使用codice_40來複制。核心語言建構期表現的加強.外部模板.在標準C++中，只要在編譯單元內遇到被完整定義的模板，編譯器都必須將其具現化。這會大大增加編譯時間，特別是模板在許多編譯單元內使用相同的引數具現化。看起來沒有辦法告訴C++不要引發模板的具現化。C++11將會構想。C++已經有了強制編譯器在特定-{zh-hans:位置; zh-hant:地點}-開始具現化的語法：template class std::vector;而C++所缺乏的是阻止編譯器在某個編譯單元內具現化模板的能力。C++11將簡單-{zh-hans:地; zh-hant:的}-擴充前文語法如下：extern template class std::vector;這樣就告訴編譯器"不要"在該編譯單元內將該模板具現化。核心語言使用性的加強.這些特色存在的主要目的是為了使C++能夠更容易使用。舉凡可以增進型別安全，減少程式碼重複，不易誤用程式碼之類的。初始化列表.標準C++從C帶來了的概念。這個構想是結構或是陣列能夠依據成員在該結構內定義的順序透過給予的一串引數來產生。這些是遞迴的，所以結構的陣列或是包含其他結構的結構可以使用它們。這對靜態列表或是僅是把結構初始化為某值而言相當有用。C++有建構函式，能夠重複物件的初始化。但單單只有那樣並不足以取代這項特色的所有機能。在C++03中，只允許在嚴格遵守POD的定義和限制條件的結構及類別上使用這項機能，非POD的型別不能使用，就連相當有用的STL容器std::vector也不行。C++11將會把初始化列表的概念綁到型別上，稱作std::initializer_list。這允許建構函式或其他函式像引數般地使用。舉例來說：class SequenceClasspublic:SequenceClass(std::initializer_list list);這將允許SequenceClass由一連串的整數構造，就像：SequenceClass someVar = {1, 4, 5, 6};這個建構函式是種特殊的建構函式，稱作。有著這種建構函式的類別在統一初始化的時候會被特別對待。類別std::initializer_list是個第一級的C++11標準程式庫型別。然而他們只能夠經由C++11編譯器透過{}語法的使用被靜態地構造。這個列表一經構造便可複製，雖然這只是copy-by-reference。初始化列表是常數；一旦被建立，其成員均不能被改變，成員中的資料也不能夠被變動。因為初始化列表是真實型別，除了類別構造式之外還能夠被用在其他地方。正規的函式能夠使用初始化列表作為形參。例如：void FunctionName(std::initializer_list list);FunctionName({1.0f, -3.45f, -0.4f});標準容器也能夠以這種方式初始化：vector v = { "xyzzy", "plugh", "abracadabra" };vector v({ "xyzzy", "plugh", "abracadabra" });vector v{ "xyzzy", "plugh", "abracadabra" };//見下節“統一的初始化”統一的初始化.標準C++在初始化型別方面有著許多問題。初始化型別有數種方法，而且交換使用時不會都產生相同結果。傳統的建構式語法，看起來像是函式宣告，而且為了能使編譯器不會弄錯必須採取一些步驟。只有集合體和POD型別能夠被集合式的初始化。C++11將會提供一種統一的語法初始化任意的物件，它擴充了初始化串列語法：struct BasicStructint x;float y;struct AltStructprivate:int x;float y;BasicStruct var1{5, 3.2f};AltStruct var2{2, 4.3f};var1的初始化的運作就如同C-style的初始化串列。每個公開的變數將被對應於初始化串列的值給初始化。隱式型別轉換會在需要的時候被使用，這裡的隱式型別轉換不會產生範圍縮限var2的初始化則是簡單地呼叫建構式。統一的初始化建構能夠免除具體指定特定型別的必要：struct IdStringstd::string name;int identifier;IdString var3{"SomeName", 4};該語法將會使用const char *引數初始化std::string。你也可以做像下面的事：IdString GetString()return {"SomeName", 4}; // 注意這裡不需要明確的型別統一初始化不會取代建構式語法。仍然會有需要用到建構式語法的時候。如果一個類別擁有，而初始化串列與建構函式的引數型別一致，那麼它比其他形式的建構式的優先權都來的高。C++11版本的std::vector將會有初始化串列建構式。這表示：std::vector theVec{4};這將會呼叫初始化串列建構式，而不是呼叫std::vector只接受一個尺寸引數產生相應尺寸vector的建構式。要使用這個建構式，使用者必須直接使用標準的建構式語法。型別推導.在C++03和C，使用變數必須明確的指出其型別。然而，隨著模版型別的出現以及模板超程式設計的技巧，某物的型別，特別是函式定義明確的回返型別，就不容易表示。在這樣的情況下，將中間結果儲存於變數是件困難的事，可能會需要知道特定的超程式設計程式庫的內部情況。C++11提供兩種方法緩解上述所遇到的困難。首先，有被明確初始化的變數可以使用codice_44關鍵字。對於指標型別，宣告為auto* 或者auto 是一樣的。對於引用型別，必須使用auto &amp; 。這會依據該初始化子的具體型別產生變數：auto integralVariable = 5;auto unsignedVariable = 5UL;auto ptrToObject = new MyPackage::Object();在上面的簡易例子中，程式設計師和編譯器都能輕易判斷出幾個變數的型別。而透過使用codice_45字尾，codice_46的型別自動成為codice_47。最後，動態建立物件時已經要在 codice_48 後輸入型別，此時使用 codice_44 就能省略掉累贅的codice_50宣告。using namespace std::placeholders;auto someStrangeCallableType = std::bind(&amp;SomeFunction, _2, _1, someObject);auto otherVariable = 5;上面的例子中說明codice_44有利於C++支援函數語言程式設計。這裡注意codice_52也是C++11從Boost C++ Libraries中引入的模版函式。codice_52實現了偏函式，在上面的例子中它將函式codice_54的第三個引數繫結為codice_55，並將第一和第二個引數的在引數列表中的順序倒轉，由此生成一個函式物件codice_56。該函式物件的型別非常複雜，但編譯器卻能輕易地將其推匯出來。除此之外，codice_57能夠被用來在編譯期決定一個表示式的型別。舉例：int someInt;decltype(someInt) otherIntegerVariable = 5;codice_57和codice_44一起使用會更為有用，因為auto變數的型別只有編譯器知道。然而codice_57對於那些大量運用運運算元過載和特化的型別的程式碼的表示也非常有用。codice_44對於減少冗贅的程式碼也很有用。舉例而言，程式員不用寫像下面這樣：for (vector::const_iterator itr = myvec.cbegin(); itr != myvec.cend(); ++itr)而可以用更簡短的for (auto itr = myvec.cbegin(); itr != myvec.cend(); ++itr)由於"myvec"實現了begin/end迭代器，C++11提供了基於範圍的--迴圈來大幅度省略程式碼。for (auto&amp; x : myvec)這項差異隨著程式員開始巢狀容器而更為顯著，雖然在這種情況下codice_62是一個減少程式碼的好方法。codice_57所表示的型別可以和codice_44推匯出來的不同。int main()const std::vector v(1);auto a = v[0]；// a為int型別decltype（v[0]) b = 0; // b為const int&amp;型別，即// std::vector::operator[]const的回返型別auto c = 0; // c為int型別auto d = c; // d為int型別decltype(c) e; // e為int型別，c實體的型別decltype((c)) f = e; // f為int&amp;型別，因為是左值decltype(0) g; // g為int型別，因為0是右值基於範圍的for迴圈.for語句將允許簡單的範圍迭代：int my_array[5] = {1, 2, 3, 4, 5};// double the value of each element in my_array:for (int &amp;x : my_array)x *= 2;// similar but also using type inference for array elementsfor (auto &amp;x : my_array) {x *= 2;上面for述句的第一部份定義被用來做範圍迭代的變數，就像被宣告在一般for迴圈的變數一樣，其作用域僅只於迴圈的範圍。而在":"之後的第二區塊，代表將被迭代的範圍。這種for語句還可以用於C型陣列，初始化列表，和任何定義了codice_65和codice_66來返回首尾迭代器的型別。Lambda函式與表示式.在標準C++，特別是當使用C++標準程式庫演演算法函式諸如sort和find，使用者經常希望能夠在演演算法函式呼叫的附近定義一個臨時的述部函式。由於語言本身允許在函式內部定義類別，可以考慮使用函式物件，然而這通常既麻煩又冗贅，也阻礙了程式碼的流程。此外，標準C++不允許定義於函式內部的類別被用於模板，所以前述的作法是不可行的。C++11對lambda的支援可以解決上述問題。一個lambda函式可以用如下的方式定義：這個不具名函式的回返型別是decltype(x+y)。只有在lambda函式符合"return "expression""的形式下，它的回返型別才能被忽略。在前述的情況下，lambda函式僅能為一個述句。在一個更為複雜的例子中，回返型別可以被明確的指定如下：本例中，一個暫時的變數z被建立用來儲存中間結果。如同一般的函式，z的值不會保留到下一次該不具名函式再次被呼叫時。如果lambda函式沒有傳回值，其回返型別可被完全忽略。定義在與lambda函式相同作用域的變數參考也可以被使用。這種的變數集合一般被稱作closure。[] // 沒有定義任何變數。使用未定義變數會引發錯誤。[x, &amp;y] // x以傳值方式傳入，y以引用方式傳入。[&amp;] // 任何被使用到的外部變數都隱式地以引用方式加以引用。[=] // 任何被使用到的外部變數都隱式地以傳值方式加以引用。[&amp;, x] // x顯式地以傳值方式加以引用。其餘變數以引用方式加以引用。[=, &amp;z] // z顯式地以引用方式加以引用。其餘變數以傳值方式加以引用。closure被定義與使用如下：std::vector someList;int total = 0;std::for_each(someList.begin(), someList.end(), [&amp;total](int x) {total += x;std::cout « total;上例可計算someList元素的總和並將其印出。變數total是lambda函式closure的一部分，同時它以引用方式被傳遞入謂詞函式，因此它的值可被lambda函式改變。若不使用引用的符號"&amp;"，則代表變數以傳值的方式傳入lambda函式。讓使用者可以用這種表示法明確區分變數傳遞的方法：傳值，或是傳參考。由於lambda函式可以不在被宣告的地方就地使用；這種情況下，若變數是以傳參考的方式連結到closure中，是無意義甚至是危險的行為。若lambda函式只在定義的作用域使用，則可以用[&amp;]宣告lambda函式，代表所有引用到stack中的變數，都是以參考的方式傳入，不必一一顯式指明：std::vector someList;int total = 0;std::for_each(someList.begin(), someList.end(), [&amp;](int x) {total += x;變數傳入lambda函式的方式可能隨實做有所變化，一般期望的方法是lambda函式能保留其作用域函式的stack指標，藉此存取區域變數。若使用[=]而非[&amp;]，則代表所有的參考的變數都是傳值使用。對於不同的變數，傳值或傳參考可以混和使用。比方說，使用者可以讓所有的變數都以傳參考的方式使用，但帶有一個傳值使用的變數：int total = 0;int value = 5;[&amp;, value](int x) { total += (x * value); };total是傳參考的方式傳入lambda函式，而value則是傳值。若一個lambda函式被定義於某類別的成員函式中，則可以使用該類別物件的參考，並且能夠存取其內部的成員。[](SomeType *typePtr) { typePtr-&gt;SomePrivateMemberFunction(); };這只有當該lambda函式建立的作用域是在SomeType的成員函式內部時才能運作。在成員函式中指涉物件的this指標，必須要顯式的傳入lambda函式，否則成員函式中的lambda函式無法使用任何該物件的變數或函式。[this]() { this-&gt;SomePrivateMemberFunction(); };若是lambda函式使用[&amp;]或是[=]的形式，this在lambda函式即為可見。lambda函式是編譯器從屬型別的函式物件；這種型別名稱只有編譯器自己能夠使用。如果使用者希望將lambda函式作為引數傳入，該型別必須是模版型別，或是必須建立一個std::function去獲取lambda的值。使用auto關鍵字讓我們能夠儲存lambda函式：auto myLambdaFunc = [this]() { this-&gt;SomePrivateMemberFunction(); };auto myOnheapLambdaFunc = new auto([=] { /*...*/ });lambda函式按照值方式捕獲的環境中的變數，是不能修改的。否則，編譯器會報錯：“by copy capture cannot be modified in a non-mutable lambda”。其值是lambda函式定義時捕獲的值，不再改變。如果在lambda函式定義時加上mutable關鍵字，則該捕獲的傳值變數是可以修改的，對同一個lambda函式的隨後呼叫也會累加影響該捕獲的傳值變數，但對外界環境中被捕獲的那個變數無影響。例如：using namespace std;int main()size_t t = 9;auto f = [t]() mutable {return t; };cout « f() « endl;t = 100;cout « f() « endl;cout « "t:" « t « endl;return 0;返回型別後置的函式宣告.標準C函式宣告語法對於C語言已經足夠。演化自C的C++除了C的基礎語法外，又擴充額外的語法。然而，當C++變得更為複雜時，它暴露出許多語法上的限制，特別是針對函式模板的宣告。下面的範例，不是合法的C++03：templateRet AddingFunc(const LHS &amp;lhs, const RHS &amp;rhs) {return lhs + rhs;} //Ret的型別必須是(lhs+rhs)的型別Ret的型別由LHS與RHS相加之後的結果的型別來決定。即使使用C++11新加入的decltype來宣告AddingFunc的返回型別，依然不可行。templatedecltype(lhs+rhs) AddingFunc(const LHS &amp;lhs, const RHS &amp;rhs) {return lhs + rhs;} //不合法的C++11不合法的原因在於lhs及rhs在定義前就出現了。直到剖析器解析到函式原型的後半部，lhs與rhs才是有意義的。針對此問題，C++11引進一種新的函式定義與宣告的語法：template這種語法也能套用到一般的函式定義與宣告：struct SomeStructauto FuncName(int x, int y) -&gt; int;auto SomeStruct::FuncName(int x, int y) -&gt; intreturn x + y;關鍵字auto的使用與其在自動型別推導代表不同的意義。物件建構的改良.在C++03中，建構式不能呼叫其它的建構式；每個建構式必須自己初始化所有的成員或是呼叫一個共用的成員函式。基礎類別的建構式不能夠直接作為衍生類別的建構式；就算基類的建構式已經足夠，每個衍伸的類別仍必須實做自己的建構式。類別中non-constant的資料成員不能夠在宣告的地方被初始化，它們只能在建構式中被初始化。C++11將會提供這些問題的解決方案。C++11允許建構式呼叫其他建構式，這種做法稱作委託。Java以及C♯都有提供這種功能。C++11語法如下：class SomeType {int number;string name;public:class DCExcept{public:DCExcept(double d)try : DCExcept(1, d){cout « "run the body." « endl;}catch(...){cout « "caught exception."«endl;private:DCExcept(int i, double d){cout « "going to throw" « endl;throw 0;int type;double date;C++03中，建構式執行結束代表物件建構完成；而允許使用轉接建構式的C++11則是以"任何"一個建構式結束代表建構完成。使用委託的建構式，函式本體中的程式碼將於被委託的建構式完成後繼續執行。若基類使用了委託建構式，則衍生類別的建構式會在"所有"基底類別的建構式都完成後，才會開始執行。C++11允許衍生類別手動繼承基底類別的建構式，編譯器可以使用基底類別的建構式完成衍生類別的建構。而將基類的建構式帶入衍生類的動作，無法選擇性地部分帶入，要不就是繼承基類全部的建構式，要不就是一個都不繼承。而衍生類別的新加入的建構式也不可以和繼承而來的基底建構式有相同的函式簽名，因為這相當於重複宣告。語法如下：class BaseClasspublic:BaseClass(int iValue);class DerivedClass : public BaseClasspublic:using BaseClass::BaseClass;此語法等同於DerivedClass宣告一個DerivedClass(int)的建構式。同時也因為DerivedClass有了一個繼承而來的建構式，所以不會有預設建構式。另一方面，C++11可以使用以下的語法完成資料成員的原地（in-place)初始化：class SomeClasspublic:private:int iValue = 5;若是建構式中沒有設定iValue的初始值，則會採用類別定義中的成員初始化，令iValue初值為5。在上例中，無引數版本的建構式，iValue便採用預設所定義的值；而帶有一個整數引數的建構式則會以指定的值完成初始化。成員初始化除了上例中的賦值形式。顯式虛擬函式過載.在C++裡，在子類別中容易意外的過載虛擬函式。舉例來說：struct Base {virtual void some_func();struct Derived : Base {void some_func();codice_67的真實意圖為何？程式設計師真的試圖過載該虛擬函式，或這只是意外？這也可能是codice_68的維護者在其中加入了一個與codice_67同名且擁有相同簽名的虛函式。另一個可能的狀況是，當基類中的虛函式的簽名被改變，子類中擁有舊簽名的函式就不再過載該虛函式。因此，如果程式設計師忘記修改所有子類，執行期將不會正確呼叫到該虛函式正確的實現。C++11將加入支援用來防止上述情形產生，並在編譯期而非執行期捕獲此類錯誤。為保持向後相容，此功能將是選擇性的。其語法如下：struct Base {virtual void some_func(float);struct Derived : Base {virtual void some_func(int) override; // 錯誤格式：Derive::some_func並沒有override Base::some_funcvirtual void some_func(float) override; // OK：顯式改寫編譯器會檢查基底類別是否存在一虛擬函式，與衍生類別中帶有宣告codice_70的虛擬函式，有相同的函式簽名；若不存在，則會回報錯誤。C++11也提供指示字codice_71，用來避免類別被繼承，或是基底類別的函式被改寫：struct Base1 final { };struct Derived1 : Base1 { }; // 錯誤格式：class Base1已標明為finalstruct Base2 {virtual void f() final;struct Derived2 : Base2 {void f(); // 錯誤格式：Base2::f已標明為final以上的範例中，codice_72宣告一新的虛擬函式，同時也表明禁止衍生函式改寫原虛擬函式。codice_70與codice_71都不是語言關鍵字使用。空指標.早在1972年，C語言誕生的初期，常數0帶有常數及空指標的雙重身分。C使用preprocessor macro codice_75表示空指標，讓codice_75及codice_77分別代表空指標及常數0。codice_75可被定義為codice_79或是codice_77。C++並不採用C的規則，不允許將codice_81隱式轉換為其他型別的指標。為了使程式碼codice_82能透過編譯，NULL只能定義為codice_77。這樣的決定使得函式多載無法區分程式碼的語意：void foo(char *);void foo(int);void foo(nullptr_t);C++建議codice_75應當定義為codice_77，所以codice_86將會呼叫codice_87，這並不是程式設計師想要的行為，也違反了程式碼的直觀性。0的歧義在此處造成困擾。C++11引入了新的關鍵字來代表空指標常數：codice_88，將空指標和整數0的概念拆開。codice_88的型別為codice_90，能隱式轉換為任何指標或是成員指標的型別，也能和它們進行相等或不等的比較。而codice_88不能隱式轉換為整數，也不能和整數做比較。為了向下相容，codice_77仍可代表空指標常數。char* pc = nullptr; // OKint * pi = nullptr; // OKint i = nullptr; // errorbool b = nullptr; // OKfoo(pc); // 呼叫foo(char *), 而不是 foo(int);foo(nullptr); // 呼叫foo(nullptr_t);值得注意的是上面的 foo(nullptr_t) 被隱式轉換為 foo(char *) 只會發生在該函式不存在其它的指標型別過載。在C++11的標準型別標頭檔案中，nullptr_t 型別應該被宣告為：typedef decltype(nullptr) nullptr_t;而不是：typedef int nullptr_t; // C++11之前的標準需要定義 NULL 為 0typedef void *nullptr_t; // ANSI C 定義 NULL 為 ((void*)0)強型別列舉.在C++03中，列舉型別不是型別安全的。列舉型別被視為整數，這使得兩種不同的列舉型別之間可以進行比較。C++03唯一提供的安全機制是一個整數或一個列舉型值不能隱式轉換到另一個列舉別型。此外，列舉所使用整數型別及其大小都由實作方法定義，皆無法明確指定。最後，列舉的名稱全數暴露於列舉型別的作用域中，因此兩個不同的列舉，不可以有相同的列舉名。C++11引進了一種特別的"列舉類"，可以避免上述的問題。使用enum class的語法來宣告：enum class myEnumerationVal1,Val2,Val3 = 100,Val4 /* = 101 */,此種列舉為型別安全的。列舉類別不能隱式地轉換為整數；也無法與整數數值做比較。。列舉類別所使用型別必須顯式指定。在上面的範例中，使用的是預設型別int，但也可以指定其他型別：enum class Enum2 : unsigned int {Val1, Val2};列舉類別的作用域不包含列舉值的名字。使用列舉值的名字，必須明確限定於其所屬的列舉型別。例如，前述列舉類別Enum2，Enum2::Val1是有意義的表示法，而單獨的Val1則否。此外，C++11允許為傳統的列舉指定使用型別：enum Enum3 : unsigned long {Val1 = 1, Val2};列舉名Val1定義於Enum3的列舉範圍中，但為了向後相容性，Val1仍然可以於所屬列舉型別所在的作用域中單獨使用。在C++11中，列舉類別的前置宣告也是可行的，只要使用可指定型別的新式列舉即可。之前的C++無法寫出列舉的前置宣告，是由於無法確定列舉變數所佔的空間大小，C++11解決了這個問題：enum Enum1; // C++與C++11中不合法;無法判別大小enum Enum2 : unsigned int; // 合法的C++11enum class Enum3; // 合法的C++11，列舉類別使用預設型別intenum class Enum4: unsigned int; // 合法的C++11enum Enum2 : unsigned short; // 不合法的C++11，Enum2已被宣告為unsigned int角括號.C++03的剖析器一律將"»"視為右移運運算元。但在巢狀樣板定義式中，絕大多數的場合其實都代表兩個連續右角括號。為了避免剖析器誤判，撰碼時不能把右角括號連著寫。C++11變更了剖析器的解讀規則；當遇到連續的右角括號時，會在合理的情況下將右尖括號解析為樣板引數的結束符號。給使用codice_94,codice_95,codice_96的表示式加上圓括號，可以避免其與圓括號外部的左尖括號相匹配：template class SomeType;std::vector"，// 非法的表示式，整數1被轉換為bool型別truestd::vector",// 合法的C++11表示式，(1&gt;2)被轉換為bool型別false顯式型別轉換子.C++98引入了關鍵字explicit來避免使用者自定的單引數建構式被當成隱式型別轉換子。但是，卻沒有限制明確定義的型別轉換函式。比方說，一個smart pointer類別具有一個operator bool()，被定義成若該smart pointer不為null則傳回true，反之傳回false。遇到這樣的程式碼時：if(smart_ptr_variable)，編譯器可以藉由operator bool()隱式轉換成布林值，和測試原生指標的方法一樣。但是這類隱式轉換同樣也會發生在非預期之處。由於C++的bool型別也是算術型別，能隱式換為整數甚至是浮點數。拿物件轉換出的布林值做布林運算以外的數學運算，往往不是程式設計師想要的。在C++11中，關鍵字explicit修飾符也能套用到型別轉換函式上。如同建構式一樣，它能避免型別轉換函式被隱式轉換呼叫。但C++11特別指定，在if條件式、迴圈、邏輯運算等需要布林值的地方，將其作為顯式型別轉換，因此即使對應的型別轉換函式被explicit修飾也可以呼叫。這主要為了解決safe bool問題。模板的別名.在進入這個主題之前，各位應該先弄清楚「模板」和「型別」本質上的不同。class template (類別模板，是模板)是用來產生template class。在C++03中，codice_62可定義模板類別一個新的型別名稱，但是不能夠使用codice_62來定義模板的別名。舉例來說：templateclass SomeType;templatetypedef SomeType TypedefName; // 在C++03是不合法的這不能夠透過編譯。為了定義模板的別名，C++11將會增加以下的語法：templateclass SomeType;templateusing TypedefName = SomeType;using也能在C++11中定義一般型別的別名，等同typedef：typedef void (*PFD)(double); // 傳統語法using PFD = void (*)(double); // 新增語法模板引數的預設值.C++98支援類模板的模板引數預設值，不支援函式模板的模板引數預設值。C++11可以支援函式模板的模板引數預設值。類模板的模板引數預設值需要從右到左依次出現；函式模板的預設模板引數沒有此約束。void DefParm(int m = 3) {} // c++98編譯透過，c++11編譯透過templateclass DefClass {}; // c++98編譯透過，c++11編譯透過templatevoid DefTempParm() {}; // c++98編譯失敗，c++11編譯透過//以下為C++11編譯：templateclass DefClass1 {};templateclass DefClass2 {}; // ERROR: 無法透過編譯：因為模板引數的預設值沒有遵循“由右往左”的規則templateclass DefClass3 {};templateclass DefClass4 {}; // ERROR: 無法透過編譯：因為模板引數的預設值沒有遵循“由右往左”的規則templatevoid DefFunc1(T1 a, T2 b) {}; // OK 函式模板不用遵循“由右往左”的規則templatevoid DefFunc2(T a) {}; // OK 函式模板不用遵循“由右往左”的規則//通常，如果能夠從函式實參中推匯出型別的話，那麼預設模板引數就不會被使用，反之，預設模板引數則可能會被使用：templatevoid f(T t = 0, U u = 0) {};void g()f(1, 'c'); // f(1, 'c')f(1); // f(1, 0), 使用了預設模板引數doublef(); // 錯誤: T無法被推匯出來f(0, 0), 使用了預設模板引數doublef(0, 0)無限制的unions.在C++03中，並非任意的型別都能做為union的成員。比方說，帶有non-trivial 建構式的型別就不能是union的成員。在新的標準裡，移除了所有對union的使用限制，除了其成員仍然不能是引用型別。這一改變使得union更強大，更有用，也易於使用。但是如果union成員具有非平凡的特殊成員函式，則編譯器不會為union生成對應的特殊成員函式，必須手工定義。以下為C++11中union使用的簡單範例：struct Pointint x_, y_;union Uint z;double w;Point p; // 在C++03中是不合法，但是在C++11是合法的U() {} // 由於 Point 成員的存在，必須要定義一個建構函式U(const Point&amp; pt) : p(pt) {} // 透過初始化列表構造 Point 物件U&amp; operator=(const Point&amp; pt) { new (&amp;p) Point(pt); return *this; } // 透過原地new方式賦值構造Point物件這一改變僅放寬union的使用限制，不會影響既有的舊程式碼。核心語言能力的提升.這些特性讓C++語言能夠做一些以前做不到的，或者極其複雜的，或者需求一些不可移植的庫的事情。可變引數模板.在C++11之前，不論是類模板或是函式模板，都只能按其被宣告時所指定的樣子，接受一組固定數目的模板引數；C++11加入新的表示法，允許任意長度、任意型別的模板引數，不必在定義時將引數的個數固定。template class tuple;模板類tuple的物件，能接受不限個數的typename作為它的模板引數：class tuple someInstanceName;-{zh-hans:實參; zh-hant:引數}-的個數也可以是0，所以class tuple someInstanceName這樣的定義也是可以的。若不希望產生-{zh-hans:實參; zh-hant:引數}-個數為0的不定長引數模板，則可以採用以下的定義：template class tuple;不定長引數模板也能運用到模板函式上。傳統C中的printf函式，雖然也能達成不定長度的引數的呼叫，但其並非型別安全。以下的範例中，C++11除了能定義型別安全的不定長引數函式外，還能讓類似printf的函式能自然地處理非內建型別的物件。除了在模板引數中能使用"..."表示不定長模板引數外，函式引數也使用同樣的表示法代表不定長引數。template void printf(const std::string &amp;strFormat, Params... parameters);其中，Params與parameters分別代表模板與函式的不定長引數集合，稱之為引數包。引數包必須要和運算元"..."搭配使用，避免語法上的歧義。不定長引數模板中，不定長引數包無法如同一般引數在類或函式中使用；因此典型的手法是以遞迴的方法取出可用引數，參看以下的C++11 printf範例：void printf(const char *s)while (*s)if (*s == '%' &amp;&amp; *(++s) != '%')throw std::runtime_error("invalid format string: missing arguments");std::cout « *s++;templatevoid printf(const char* s, T value, Args... args)while (*s)if (*s == '%' &amp;&amp; *(++s) != '%')std::cout « value;printf(*s ? ++s : s, args...); // 即便當*s == 0也會產生呼叫，以檢測更多的型別引數。return;std::cout « *s++;throw std::logic_error("extra arguments provided to printf");printf會不斷地遞迴呼叫自身：函式引數包args...在呼叫時，會被模板型別匹配分離為T value和Args... args。直到args...變為空引數，則會與簡單的printf(const char *s)形成匹配，結束遞迴。另一個例子為計算模板引數的長度，這裡使用相似的技巧展開模板引數包Args...：templatestruct Count{};templatestruct count {static const int value = 0;templatestruct count {static const int value = 1 + count::value;-{zh-hans:雖然沒有一個簡潔的機制能夠對變長引數模板中的值進行迭代; zh-hant:雖然沒有很簡單的機制能個別依序處理變長引數模板的引數}-，但使用運算元"..."還能在程式碼各處對引數包施以更複雜的展開操作。舉例來說，一個模板類的定義：template  class ClassName : public BaseClasses...public:BaseClasses...會被展開成類別ClassName的基底類；ClassName的建構式需要所有基底類的右值引用，而每一個基底類都是以傳入的引數做初始化。在函式模板中，不定長引數可以和右值參照搭配，達成引數的完美轉送：template struct SharedPtrAllocatortemplate ConstructWithSharedPtr(Args&amp;&amp;... params)return std::shared_ptr(params)...));引數包parms可展開為TypeToConstruct建構式的引數。表示式std::forward(params)可將引數的型別資訊保留。此外，不定長引數的數量可以藉以下的語法得知：template struct SomeStructstatic const int size = sizeof...(Args);SomeStruct::size會是0。新的字串字面值.標準C++提供了兩種字串字面值。第一種，包含有雙引號，產生以空字元結尾的const char陣列。第二種有著前標L，產生以空字元結尾的const wchar_t陣列，其中wchar_t代表寬字元。對於Unicode編碼的支援尚付闕如。為了加強C++編譯器對Unicode的支援，型別char的定義被修改為其大小至少能夠儲存UTF-8的8位元編碼，並且能夠容納編譯器的基本字元集的任何成員。C++11將支援三種Unicode編碼方式：UTF-8，UTF-16，和UTF-32。除了上述char定義的變更，C++11將增加兩種新的字元型別：char16_t和char32_t。它們各自被設計用來儲存UTF-16以及UTF-32的字元。以下展示如何產生使用這些編碼的字串字面值：u8"I'm a UTF-8 string."u"This is a UTF-16 string."U"This is a UTF-32 string."第一個字串的型別是通常的codice_99；第二個字串的型別是codice_100；第三個字串的型別是codice_101。當建立Unicode字串字面值時，可以直接在字串內插入Unicode codepoints。C++11提供了以下的語法：u8"This is a Unicode Character: \u2018."u"This is a bigger Unicode Character: \u2018."U"This is a Unicode Character: \U00002018."在'\u'之後的是16個位元的十六進位數值；它不需要'0x'的前標。識別字'\u'代表了一個16位元的Unicode codepoint；如果要輸入32位元的codepoint，使用'\U'和32個位元的十六進位數值。只有有效的Unicode codepoints能夠被輸入。舉例而言，codepoints在範圍U+D800—U+DFFF之間是被禁止的，它們被保留給UTF-16編碼的surrogate pairs。有時候避免手動將字串換碼也是很有用的，特別是在使用XML檔案或是一些指令碼語言的字面值的時候。C++11將提供raw字串字面值：在第一個例子中，任何包含在codice_102 codice_103括號，但不能包含空格、控制字元和'('、')'、'\'。原始字串允許使用者使用圓括號codice_102,codice_103，例如R"delimiter((a-z))delimiter"等價於"(a-z)"。原始字串字面值能夠和寬字面值或是Unicode字面值結合：u8R"XXX(I'm a "raw UTF-8" string.)XXX"// uR"*@(This is a "raw UTF-16" string.)*@" //visual studio not support '@'uR"*(This is a "raw UTF-16" string.)*"UR"(This is a "raw UTF-32" string.)"使用者定義字面量.標準C++提供了數種字面值。字元"12.5"是能夠被編譯器解釋為數值12.5的double型別字面值。然而，加上"f"的後置，像是"12.5f"，則會產生數值為12.5的float型別字面值。之前的C++規範中字面值的修飾符是固定的，C++程式碼不能創立新的字面修飾符。C++11開放使用者定義新的字面修飾符，利用自訂的修飾符完成由字面值建構物件。字面值轉換可以定義為兩個階段：原始與轉換後。原始字面值指特定型別的字元序列，而轉換後的字面值則代表另一種型別。如字面值1234，原始字面值是'1', '2', '3', '4'的字元序列；而轉換後的字面值是整數值1234。另外，字面值0xA轉換前是序列'0', 'x', 'A'；轉換後代表整數值10。多工記憶體模型.C++標準委員會計劃統一對多緒程式設計的支援。這將涉及兩個部分：第一、設計一個可以使多個執行緒在一個程序中共存的記憶體模型；第二、為執行緒之間的互動提供支援。第二部分將由程式庫提供支援，更多請看緒程支援。在多個執行緒可能會訪問相同記憶體的情形下，由一個記憶體模型對它們進行排程是非常有必要的。遵守模型規則的程式是被保證正確執行的，但違反規則的程式會發生不可預料的行為，這些行為依賴於編譯器的最佳化和記憶體一致性的問題。thread-local的儲存期限.在多緒環境下，讓各緒程擁有各自的變數是很普遍的。這已經存在於函式的區域變數，但是對於全域和靜態變數都還不行。新的"thread_local"儲存期限被作為下個標準而提出。緒程區域的儲存期限會藉由儲存指定字codice_113來表明。static物件(生命週期為整個程式的執行期間)的儲存期限可以被thread-local給替代。就如同其他使用static儲存期的變數，thread-local物件能夠以建構式初始化並以解構式摧毀。使用或禁用物件的預設函式.在傳統C++中，若使用者沒有提供，則編譯器會自動為物件生成預設建構式(default constructor)、複製建構式。當使用者有需要時，也可以提供自訂的版本改寫上述的函式。問題在於原先的c++無法精確地控制這些預設函式的生成。比方說，要讓類別不能被複製，必須將複製建構式與賦值運運算元宣告為private，並不去定義它們。嘗試使用這些未定義的函式會導致編譯期或連結期的錯誤。但這種手法並不是一個理想的解決方案。此外，編譯器產生的預設建構式與使用者定義的建構式無法同時存在。若使用者定義了任何建構式，編譯器便不會生成預設建構式；但有時同時帶有上述兩者提供的建構式也是很有用的。目前並沒有顯式指定編譯器產生預設建構式的方法。C++11允許顯式地表明採用或拒用編譯器提供的內建函式。例如要求類別帶有預設建構式，可以用以下的語法：struct SomeTypeSomeType() = default; // 預設建構式的顯式宣告SomeType(OtherType value);另一方面，也可以禁止編譯器自動產生某些函式。如下面的例子，類別不可複製：struct NonCopyableNonCopyable &amp; operator=(const NonCopyable&amp;) = delete;NonCopyable(const NonCopyable&amp;) = delete;NonCopyable() = default;禁止類別以operator new配置記憶體：struct NonNewablevoid *operator new(std::size_t) = delete;此種物件只能生成於stack中或是當作其他類別的成員，它無法直接配置於heap之中，除非使用了與平臺相關，不可移植的手法。codice_114的宣告也能適用於非內建函式，禁止成員函式以特定的引數呼叫：struct NoDoublevoid f(int i);void f(double) = delete;若嘗試以double的引數呼叫codice_115，將會引發編譯期錯誤，編譯器不會自動將double引數轉型為int再呼叫codice_115。若要徹底的禁止以非int的引數呼叫codice_115，可以將codice_114與模板相結合：struct OnlyIntvoid f(int i);template void f(T) = delete;codice_119型別.在32位元系統上，一個codice_119是保有至少64個有效位元的整數型別。C99將這個型別引入了標準C中，目前大多數的C++編譯器也支援這種型別。C++11將把這種型別新增到標準C++中。靜態assertion.C++提供了兩種方法測試assertion：巨集codice_121以及前處理器指令codice_122。但是這兩者對於模版來說都不合用。巨集在執行期測試assertion，而前處理器指令則在前置處理時測試assertion，這時候模版還未能具現化。所以它們都不適合來測試牽扯到模板引數的相關特性。新的機能會引進新的方式可以在編譯期測試assertion，只要使用新的關鍵字codice_123。宣告採取以下的形式：static_assert( "constant-expression", "error-message" ) ;這裡有一些如何使用codice_123的例子：static_assert( 3.14 member); //C++98sizeof(SomeType::member); // 直接由SomeType型別取得非靜態成員的大小，C++03不行。C++11允許這會傳回OtherType的大小。C++03並不允許這樣做，所以會引發編譯錯誤。C++11將會允許這種使用。垃圾回收機制.是否會自動回收那些無法被使用到的動態分配物件由實作決定。頭檔案中的幾個函式：C++標準程式庫的變更.C++11標準程式庫有數個新機能。其中許多可以在現行標準下實作，而另外一些則依賴於新的C++11核心語言機能。新的程式庫的大部分被定義於"C++標準委員會的Library Technical Report"，於2005年發布。各式TR1的完全或部分實作目前提供在名稱空間codice_130。C++11會將其移置於名稱空間codice_131之下。標準庫元件上的升級.目前的標準庫能受益於C++11新增的一些語言特性。舉例來說，對於大部份的標準庫容器而言，像是搬移內含大量元素的容器，或是容器之內對元素的搬移，基於右值引用的codice_132建構子都能最佳化前述動作。在適當的情況下，標準庫元件將可利用C++11的語言特性進行升級。這些語言特性包含但不侷限以下所列：此外，自C++標準化之後已經過許多年。現有許多程式碼利用到了標準庫;這同時揭露了部份的標準庫可以做些改良。其中之一是標準庫的記憶體配置器。C++11將會加入一個基於作用域模型的記憶體配置器來支援現有的模型。執行緒支援.雖然C++11會在語言的定義上提供一個記憶體模型以支援執行緒，但執行緒的使用主要將以C++11標準函式庫的方式呈現。C++11標準函式庫會提供類別codice_135。若要執行一個執行緒，可以建立一個類別codice_135的實體，其初始引數為一個函式物件，以及該函式物件所需要的引數。透過成員函式codice_138對執行緒會合的支援，一個執行緒可以暫停直到其它執行緒執行完畢。若有底層平臺支援，成員函式codice_139將可提供對原生執行緒物件執行平臺特定的操作。對於執行緒間的同步，標準函式庫將會提供適當的互斥鎖和鎖相關演演算法的方式呈現，以方便程式員使用。對於要求高效能，或是極底層的工作，有時或甚至是必須的，我們希望執行緒間的通訊能避免互斥鎖使用上的開銷。以原子操作來存取記憶體可以達成此目的。針對不同情況，我們可以透過顯性的記憶體屏障改變該存取記憶體動作的可見性。對於執行緒間非同步的傳輸，C++11標準函式庫加入了以及codice_146用來包裝一個會傳回非同步結果的函式呼叫。因為缺少結合數個future的功能，和無法判定一組promise集合中的某一個promise是否完成，futures此一提案因此而受到了批評。更高階的執行緒支援，如執行緒池，已經決定留待在未來的Technical Report加入此類支援。更高階的執行緒支援不會是C++11的一部份，但設想是其最終實現將建立在目前已有的執行緒支援之上。codice_147提供了一個簡便方法以用來執行執行緒，並將執行緒繫結在codice_148。使用者可以選擇一個工作是要多個執行緒上非同步的執行，或是在一個執行緒上執行並等待其所需要的資料。預設的情況，實作可以根據底層硬體選擇前面兩個選項的其中之一。另外在較簡單的使用情形下，實作也可以利用執行緒池提供支援。多元組型別.多元組是一個內由數個異質物件以特定順序排列而成的資料結構。多元組可被視為是codice_149其資料成員的一般化。由TR1演進而來的C++11多元組型別將受益於C++11某些特色像是可變引數模板。TR1版本的多元組型別對所能容納的物件個數會因實作而有所限制，且實作上需要用到大量的巨集技巧。相反的，C++11版本的多元組型基本上於對其能容納的物件個數沒有限制。然而，編譯器對於模板實體化的遞迴深度上的限制仍舊影響了元組型別所能容納的物件個數；C++11版本的多元組型不會把這個值讓使用者知道。使用可變引數模板，多元組型別的宣告可以長得像下面這樣：template  class tuple;底下是一個多元組型別的定義和使用情況：typedef std::tuple  test_tuple;long lengthy = 12;test_tuple proof (18, 6.5, lengthy, "Ciao!");lengthy = std::get(proof); // 將proof的第一個元素賦值給lengthystd::get(proof) = " Beautiful!"; // 修改proof的第四個元素我們可以定義一個多元組型別物件codice_150而不指定其內容，前提是codice_150裡的元素其型別定義了預設建構子；否則的話，賦值運算子右邊的多元組其內含元素的型別必須能轉換成左邊的多元組其對應的元素型別，又或者賦值運算子左邊的多元組其內含元素的型別必須定義適當的建構子。std::tuple t1;std::tuple t2 ('X', 2, "Hola!");t1 = t2 ; // 可行。前兩個元素會作型別轉換，// 第三個字串元素可由'const char *'所建構。多元組型別物件的比較運算是可行的。雜湊表.在過去，不斷有要求想將雜湊表在效能上比不過平衡樹。但實際運用上，雜湊表的表現則較佳。因為標準委員會還看不到有任何機會能將開放定址法標準化，所以目前衝突僅能透過鏈地址法的方式處理。為避免與第三方函式庫發展的雜湊表發生名稱上的衝突，字首將採用unordered而非hash。函式庫將引進四種雜湊表，其中差別在於底下兩個特性：是否接受具相同鍵值的專案。上述的類別將滿足對一個容器類別的要求，同時也提供存取其中元素的成員函式：codice_157，codice_158，codice_159，codice_160。雜湊表不需要對現有核心語言做擴充套件，只會對標頭檔codice_161做些許擴充套件，並引入codice_162和codice_163兩個標頭檔。對於其它現有的類別不會有任何修改。同時，雜湊表也不會依賴其它標準庫的擴充套件功能。正規表示式.過去許多或多或少標準化的程式庫被建立用來處理正規表示式。有鑑於這些演演算法的使用非常普遍，因此標準程式庫將會包含他們，並使用各種物件導向語言的潛力。這個新的程式庫，被定義於codice_164標頭檔，由幾個新的類別所組成：函式codice_167是用來搜尋樣式；若要搜尋並取代，則要使用函式codice_168，該函式會回傳一個新的字串。演演算法codice_167和codice_168接受一個正規表示式和一個字串，並將該樣式匹配的情況儲存在struct codice_166。底下描述了codice_166的使用情況：const char *reg_esp = "[ .\\t\\n;:]" ; // 分隔字元列表std::regex rgx(reg_esp) ; // 'regex'是樣板類'basic_regex'以型別為'char'// 的引數具現化的實體std::cmatch match ; // 'cmatch'是樣板類match_results'以型別為'const char *'// '的引數具現化的實體const char *target = "Polytechnic University of Turin " ;// 辨別所有被分隔字元所分隔的字if( regex_search( target, match, rgx ) )// 若此種字存在const size_t n = match.size();for( size_t a = 0 ; a &lt; n ; a++ )string str( match[a].first, match[a].second ) ;cout « str « "\n" ;注意雙反斜線的使用，因為C++將反斜線作為跳脫字元使用。但C++11的raw string可以用來避免此一問題。函式庫不需要改動到現有的標頭檔，同時也不需要對現有的語言作擴充套件。通用智慧指標.這些指標是由TR1智慧指標演變而來。注意! 智慧指標是類別而非一般指標。codice_173是一引用計數指標，其行為與一般C++指標極為相似。在TR1的實作中，缺少了一些一般指標所擁有的特色，像是別名或是指標運算。C++11新增前述特色。一個codice_173只有在已經沒有任何其它codice_173指向其原本所指向物件時，才會銷毀該物件。一個codice_176指向的是一個被codice_173所指向的物件。該codice_176可以用來決定該物件是否已被銷毀。codice_176不能被解參考;想要存取其內部所儲存的指標，只能透過codice_173。有兩種方法可達成此目的。第一，類別codice_173有一個以codice_176為引數的建構子。第二，類別codice_176有一個名為codice_184的成員函式，其返回值為一個codice_173。codice_176並不擁有它所指向的物件，因此不影響該物件的銷毀與否。底下是一個codice_173的使用範例：int main( )std::shared_ptr p_first(new double) ;std::shared_ptr p_copy = p_first ;*p_copy = 21.2;} // 此時'p_copy'會被銷毀，但動態分配的double不會被銷毀。return 0; // 此時'p_first'會被銷毀，動態分配的double也會被銷毀。codice_188將會被C++標準所廢棄，取而代之的是codice_189。codice_189提供codice_188大部份特性，唯一的例外是codice_188的不安全、隱性的左值搬移。不像codice_188，codice_189可以存放在C++11提出的那些能察覺搬移動作的容器之中。可擴充套件的隨機數功能.C標準庫允許使用codice_195函式來生成偽隨機數。不過其演演算法則取決於各程式庫開發者。C++直接從C繼承了這部份，但是C++11將會提供產生偽亂數的新方法。C++11的隨機數功能分為兩部分：第一，一個亂數生成引擎，其中包含該生成引擎的狀態，用來產生亂數。第二，一個分佈，這可以用來決定產生亂數的範圍，也可以決定以何種分佈方式產生亂數。亂數生成物件即是由亂數生成引擎和分佈所構成。不同於C標準庫的codice_195;針對產生亂數的機制，C++11將會提供三種演演算法，每一種演演算法都有其強項和弱項：C++11將會提供一些標準分佈：uniform_int_distribution。底下描述一個亂數生成物件如何由亂數生成引擎和分佈構成：std::uniform_int_distribution distribution(0, 99); // 以離散型均勻分佈方式產生int亂數，範圍落在0到99之間std::mt19937 engine; // 建立亂數生成引擎auto generator = std::bind(distribution, engine); // 利用bind將亂數生成引擎和分佈組合成一個亂數生成物件int random = generator(); // 產生亂數包裝引用.我們可以透過實體化樣板類codice_197得到一個包裝引用。當樣板函式需要形參的引用而非其複製，這時包裝引用就能派上用場：// 此函式將得到形參'r'的引用並對r加一// 樣板函式int main()int i = 0 ;g (f, i) ; // 實體化'g'// 'i'不會被修改std::cout « i « std::endl; // 輸出0g (f, std::ref(i)); // 實體化'g&lt;void(int &amp;r),reference_wrapper&lt;int»'// 'i'會被修改std::cout « i « std::endl; // 輸出1這項功能將加入標頭檔codice_161之中，而非透過擴充套件語言來得到這項功能。多型函式物件包裝器.針對函式物件的多型包裝器。透過以下例子，我們可以瞭解多型函式物件包裝器的特性：std::function func; // 利用樣板類'function'// 建立包裝器std::plus T plus( T, T ) ;'// 因此'add'的型別是'int add( int x, int y )'func = &amp;add; // 可行。'add'的型參和回返值型別與'func'相符int a = func (1, 2); // 注意：若包裝器'func'沒有參考到任何函式// 會丟出'std::bad_function_call'例外std::function func2 ;if(!func2) { // 因為尚未賦值與'func2'任何函式，此條件式為真bool adjacent(long x, long y);func2 = &amp;adjacent ; // 可行。'adjacent'的型參和回返值型別可透過型別轉換進而與'func2'相符struct Test {bool operator()(short x, short y);Test car;func = std::ref(car); // 樣板類'std::ref'回傳一個struct 'car'// 其成員函式'operator()'的包裝func = func2; // 可行。'func2'的型參和回返值型別可透過型別轉換進而與'func'相符模板類codice_201將定義在標頭檔codice_161，而不須更動到語言本身。用於超程式設計的型別屬性.對於那些能自行建立或修改本身或其它程式的程式，我們稱之為超程式設計。這種行為可以發生在編譯或執行期。C++標準委員會已經決定引進一組由模板實現的函式庫，程式員可利用此一函式庫於編譯期進行超程式設計。底下是一個以超程式設計來計算指數的例子：templatestruct Pow {// recursive call and recombination.enum{ value = B*Pow::value };templatestruct Pow {// "N == 0" condition of termination.enum{ value = 1 };int quartic_of_three = Pow::value;許多演演算法能作用在不同的資料型別；C++模板支援泛型，這使得程式碼能更緊湊和有用。然而，演演算法經常會需要目前作用的資料型別的資訊。這種資訊可以透過型別屬性於模板實體化時將該資訊萃取出來。型別屬效能識別一個物件的種類和有關一個型別的特徵。標頭檔codice_204描述了我們能識別那些特徵。底下的例子說明瞭模板函式‘elaborate’是如何根據給定的資料型別，從而實體化某一特定的演演算法。// 演演算法一template struct Algorithm {// 演演算法二template {// 根據給定的型別，實體化之後的'elaborate'會選擇演演算法一或二templateint elaborate (T1 A, T2 B)// 若T1為int且T2為float，選用演演算法二// 其它情況選用演演算法一return Algorithm::do_it( A, B ) ;此種程式設計技巧能寫出優美、簡潔的程式碼；然而除錯是此種程式設計技巧的弱處：編譯期的錯誤訊息讓人不知所云，執行期的除錯更是困難。用於計算函式物件返回型別的統一方法.要在編譯期決定一個樣板仿函式的回返值型別並不容易，特別是當回返值依賴於函式的引數時。舉例來說：struct Clear {int operator()(int); // 引數與回返值的型別相同double operator()(double); // 引數與回返值的型別相同templateclass Calculus {public:template Arg operator()(Arg&amp; a) constreturn member(a);private:Obj member;實體化樣板類codice_206，codice_207的仿函式其回返值總是和codice_208的仿函式其回返值具有相同的型別。然而，若給定類別codice_209:struct Confused {double operator()(int); // 引數與回返值的型別不相同int operator()(double); // 引數與回返值的型別不相同企圖實體化樣板類Calculus將導致Calculus的仿函式其回返值和類別Confused的仿函式其回返值有不同的型別。對於codice_129和codice_211之間的轉換，編譯器將給出警告。模板codice_212被TR1引進且被C++11所採納，可允許我們決定和使用一個仿函式其回返值的型別。底下，codice_213物件使用codice_212物件來推導其仿函式的回返值型別：templateclass CalculusVer2 {public:templatetypename std::result_of::type operator()(Arg&amp; a) constreturn member(a);private:Obj member;如此一來，在實體化codice_215其仿函式時，不會有型別轉換，警告或是錯誤發生。模板codice_212在TR1和C++11有一點不同。TR1的版本允許實作在特殊情況下，可以無法決定一個函式呼叫其回返值型別。然而，因為C++11支援了decltype，實作被要求在所有情況下，皆能計算出回返值型別。iota 函式.iota 函式可將給定區間的值設定為從某值開始的連續值，例如將連續十個整數設定為從 1 開始的連續整數。std::array ai;std::iota(ai.begin(), ai.end(), 1);for(int i: ai){std::cout«i«" ";//1 2 3 4 5 6 7 8 9 10已被移除或是不包含在C++11標準的特性.預計由Technical Report提供支援：延後討論：編譯器實現.C++編譯器對C++11新特性的支援情況：