C11，先前被稱作 C0x，即 ISOIEC 148822011，是 C 程式語言的一個標準。它取代第二版標準 ISOIEC 148822003（第一版 ISOIEC 148821998 公開於 1998 年，第二版於 2003 年更新，分別通稱 C98 以及 C03，兩者差異很小），且已被 C14 取代。相比於 C03，C11 標準包含核心語言的新機能，而且擴充套件 C 標準程式庫，併入了大部分的 C Technical Report 1 程式庫（數學的特殊函式除外）。 ISO／IEC JTC1SC22WG21 C 標準委員會計劃在 2010 年 8 月之前完成對最終委員會草案的投票，以及於 2011 年 3 月召開的標準會議完成國際標準的最終草案。然而，WG21 預期 ISO 將要花費六個月到一年的時間才能正式釋出新的 C 標準。為了能夠如期完成，委員會決定致力於直至 2006 年為止的提案，忽略新的提案。最終於 2011 年 8 月 12 日公佈，並於 2011 年 9 月出版。 2012 年 2 月 28 日的國際標準草案是最接近於 C11 標準的草案，差異僅有編輯上的修正。 像 C 這樣的程式語言，透過一種演化的過程來發展其定義。這個過程不可避免地將引發與現有程式碼的相容問題，在 C 的發展過程中偶爾會發生。不過根據比雅尼斯特勞斯特魯普（C 的創始人並且是委員會的一員）表示，新的標準將幾乎 100 相容於現有標準。 設計原則 C 的修訂包含核心語言以及標準程式庫。 在發展新標準的每個機能上，委員會採取了幾個方向： 維持穩定性和與 C98，可能的話還有 C 之間的相容性； 儘可能不透過核心語言的擴充套件，而是透過標準程式庫來引進新的特性； 能夠演進程式設計技術的變更優先； 改進 C 以幫助系統以及函式庫設計，而不是引進只針對特別應用的新特性； 增進型別安全，提供對現行不安全的技術更安全的替代方案； 增進直接對硬體工作的能力與表現； 提供現實世界中問題的適當解決方案； 實行 zerooverhead 原則（某些功能要求的額外支援只有在該功能被使用時才能使用）； 使 C 易於教授與學習 關照初學者被認為是重要的，因為他們構成了計算機程式設計師的主體。也因為許多初學者不願擴充套件他們對 C 的知識，只限於使用他們對 C 專精的部分。此外，考慮到 C 被廣泛的使用（包含應用領域和程式設計風格），即便是最有經驗的程式設計師在面對新的程式設計正規化時也會成為初學者。 C 核心語言的擴充 C 委員會的主要作用之一是改善語言核心。核心語言將被大幅改善的領域包括多執行緒支援、泛型程式設計、統一的初始化，以及效能表現的加強。 在此分成 4 個區塊來討論核心語言的特色以及變更： 執行期表現強化、建構期表現強化、可用性強化，還有新的功能。某些特性可能會同時屬於多個區塊，但在此僅於其最具代表性的區塊描述。 核心語言的執行期表現強化 以下的語言機能主要用來提升某些效能表現，像是記憶體或是速度上的表現。 右值引用和 move 語意 在 C03 及之前的標準，臨時物件（稱為右值 Rvalues，因為它們通常位於賦值運運算元右側）無法被改變，在 C 中亦同（且被視為等同於 const T）。儘管如此，在某些情況下臨時物件仍然可能會被改變，但這種表現也被視為是一個有用的漏洞。 C11 增加一個新的非常數引用（reference）型別，稱作右值引用（Rvalue reference），標記為 T 。右值引用所繫結的臨時物件可以在該臨時物件被初始化之後做修改，這是為了允許 move 語意。 C03 低效能問題的之一，就是在以傳值方式傳遞物件時隱式發生的耗時且不必要的深度複製。舉例而言，stdvectorT 本質上是一個 Cstyle 陣列及其大小的封裝，如果一個 stdvectorT 的臨時物件是在函式內部或者函式返回時建立，要將其儲存就只能透過生成新的 stdvectorT 並且把該臨時物件所有的資料複製過去（為了討論上的方便，這裡忽略返回值最佳化）。然後該臨時物件會被析構，其使用的記憶體會被釋放。 在 C11，把一個 vector 的右值引用作為引數 stdvector 的 move 建構子，可以把右值引數所繫結的 vector 內部的指向 Cstyle 陣列的指標複製給新的 vector，然後把該指標置 null。由於臨時變數不會被再次使用，所以不會有程式碼去訪問該 null 指標；又因為該指標為 null，當該臨時物件超出作用域時曾經指向的內部 Cstyle 陣列所使用的記憶體不會被釋放。因此，該操作不僅無形中免去了深複製的開銷，而且還很安全。 右值引用作為資料型別的引入，使得函式可以過載區分它的引數是值型別、傳統的左值引用還是右值引用。這讓除了標準庫的現有程式碼無須任何改動就能等到效能提升。一個返回 stdvectorT 的函式的返回型別無須為了呼叫 move 建構函式而顯式修改為 stdvectorT，因為臨時物件自動作為右值。（但是，如果 stdvectorT 是沒有 move 建構函式的 C03 版，由於傳統的左值引用也可以繫結到臨時物件上，因此具有 const stdvectorT 引數的複製建構函式會被呼叫，導致一次顯著的記憶體分配。） 出於安全的考慮，推行了一些限制。具名的變數被認定為左值，即使它是被宣告為右值引用資料型別；為了獲得右值必須使用顯式型別轉換，如模板函式 stdmoveT。右值引用所繫結的物件應該只在特定情境下被修改，主要用於 move 建構函式中。 bool is_r_value int return true bool is_r_value const int return false void test int i is_r_value i i 為具名變數，即使被宣告成右值引用型別，i 作為實參表示式也不會被認定是右值表示式。 is_r_value stdmoveinti 使用 stdmoveT 取得右值。 由於右值引用的語義特性以及對於左值引用（Lvalue referencesregular references）的某些語義修正，右值引用讓開發者能夠提供函式引數的完美轉發（perfect function forwarding）。當與不定長引數模板結合，這項能力允許函式模板能夠完美地轉送引數給其他接受這些特定引數的函式。最大的用處是轉送建構子引數，創造出能夠自動為這些特定引數呼叫正確建構式的工廠函式（factory function）。這個用法可以在 C 標準庫中的 emplace_back 方法中看到。 constexpr 泛化的常數表示式 C 本來就已具備常數表示式（constant expression）的概念。像是 34 總是會產生相同的結果並且沒有任何的副作用。常數表示式對編譯器來說是最佳化的機會，編譯器時常在編譯期執行它們並且將值存入程式中。同樣地，在許多場合下，C 規格要求使用常數表示式。例如在陣列大小的定義上，以及列舉值（enumerator values）都要求必須是常數表示式。 然而，常數表示式不能含有函式呼叫或是物件建構式。所以像是以下的例子是不合法的： int GetFive return 5 int some_value GetFive 7； 欲產生 12 個整數的陣列。不合法的 C 寫法 這在 C03 中是不合法的，因為 GetFive 7 並不是常數表示式。C03 編譯器無從得知 GetFive 實際上在執行期是常數。理論上而言，這個函式可能會影響全域變數，或者呼叫其他的非執行期（nonruntime）常數函式等。 C11 引進關鍵字 constexpr 允許使用者保證函式或是物件建構式是編譯期常數。以上的例子可以被寫成像是下面這樣： constexpr int GetFive return 5 int some_value GetFive 7； 欲產生 12 個整數的陣列。合法的 C11 寫法 這使得編譯器能夠瞭解並去驗證 GetFive 是個編譯期常數。 用 constexpr 修飾函式將限制函式的行為。首先，該函式的回返值型別不能為 void。第二，函式的內容必須依照 return expr 的形式。第三，在引數替換後，expr 必須是個常數表示式。這些常數表示式只能夠呼叫其他被定義為 constexpr 的函式，或是其他常數表示式的資料變數。最後，有著這樣修飾符的函式直到在該編譯單元內被定義之前是不能夠被呼叫的。 宣告為 constexpr 的函式也可以像其他函式一樣用於常量表達式以外的地方，此時不需要滿足後兩點。 C11 之前，可以在常量表達式中使用的變數必須被宣告為 const，用常量表達式來初始化，並且必須是整型或列舉型別。C11 去除了變數必須是整型或列舉型別的限制，只要變數使用了 constexpr 關鍵字來定義： constexpr double earth_gravitational_acceleration 98 constexpr double moon_gravitational_acceleration earth_gravitational_acceleration 60 這些變數都是隱式常量，必須使用常量表達式來初始化。 為了讓使用者自定義型別（userdefined type）參與建構常量表示式，建構式也可以用 constexpr 來宣告。與 constexpr 函式一樣，constexpr 建構式必須在該編譯單元內使用之前被定義。它的函式體必須為空。它必須用常量表示式初始化他的成員（member）。而這種型別的解構式應當是平凡的（trivial）。 擁有 constexpr 建構函式的型別的複製建構函式通常也應該被定義為 constexpr，以便該型別的物件以值傳遞的方式從 constexpr 函式返回。該類別的任何成員函式，像是複製建構式、運算子過載函式等等，只要他們符合常數表示式函式的定義，都可以被宣告成 constexpr。使得編譯器能夠在編譯期進行類別的複製、對他們施行運算等等。 常數表示式函式或建構式，可以以非常數表示式（nonconstexpr）作為引數喚起。就如同 constexpr 整數字面值能夠指派給 nonconstexpr 變數，constexpr 函式也可以接受 nonconstexpr 引數，其結果儲存於 nonconstexpr 變數。constexpr 關鍵字只有當表示式的成員都是 constexpr，才允許編譯期常數性的可能。 對 POD 定義的修正 在 C03 中，一個類（class）或結構（struct）要想被作為 POD，必須遵守幾條規則。符合這種定義的型別能夠產生與 C 相容的物件記憶體佈局（object layout），而且可以被靜態初始化。但 C03 標準嚴格限制了何種型別與 C 相容或可以被靜態初始化的，儘管並不存在技術原因導致編譯器無法處理。如果建立一個 C03 POD 型別，然後為其新增一個非虛成員函式，這個型別就不再是 POD 型別了，從而無法被靜態初始化，也不再與 C 相容，儘管其記憶體佈局並沒有發生變化。 C11 透過把 POD 概念劃分成兩個概念：平凡的（trivial）和標準佈局（standardlayout），放寬了關於 POD 的定義。 一個平凡的型別可以被靜態初始化，意味著使用 memcpy 來複制資料是合法的，而無須使用複製建構函式。平凡的型別物件的生命週期開始於其儲存空間被分配時，而不是其建構函式完成時。使用模版類 stdis_trivialTvalue 來判斷資料型別是否為平凡型別 一個平凡的類別或結構符合以下定義： 平凡的預設建構式。這可以使用預設建構式語法，例如 SomeConstructor default 平凡的複製建構式和 move 建構函式，可使用預設語法（default syntax） 平凡的賦值運運算元和 move 賦值運算子，可使用預設語法（default syntax） 平凡的解構式，不可以是虛擬函式（virtual） 類沒有虛基類和虛成員函式 複製建構函式和賦值運算子還額外要求所有非靜態資料成員都是平凡的。 一個符合標準佈局的類封裝成員的方式與 C 相容。使用模版類 stdis_standard_layoutAvalue 來判斷型別是否是一個標準佈局型別。一個標準佈局（standardlayout）的類別或結構符合以下定義： 所有 nonstatic 成員有相同的存取控制（public，private，protected） 沒有虛擬函式 沒有虛基類 所有基礎類別符合標準佈局 所有非靜態的（nonstatic）資料成員屬於符合標準佈局的類別 類中第一個非靜態類別與基類不是同一個類別。例如：struct AB B b int c 不符合要求 兩種情況必局其一：或者所有基礎類別都沒有 nonstatic 成員；或者最派生類別沒有 nonstatic 資料成員且至多一個帶有 nonstatic 成員的基礎類別。基本上，在該類別的繼承體系中只會有一個類別帶有 nonstatic 成員。 一個類、結構、聯合只有在其是平凡的、符合標準佈局，並且所有非靜態成員和基類都是 POD 時，才被視為 POD。使用 type_traits 中的 is_podTvalue 判斷 T 是不是 POD 型別 透過劃分，使得放棄一個特性而不失去另一個成為可能。一個具有複雜的複製和 move 建構函式的類可能不是平凡的，但是它可能符合標準佈局，從而能與 C 程式互動。類似地，一個同時具有 public 和 private 資料成員的類不符合標準佈局，但它可以是平凡的，從而能夠使用 memcpy 來複制。 核心語言建構期表現的加強 外部模板 在標準 C 中，只要在編譯單元內遇到被完整定義的模板，編譯器都必須將其具現化（instantiate）。這會大大增加編譯時間，特別是模板在許多編譯單元內使用相同的引數具現化。看起來沒有辦法告訴 C 不要引發模板的具現化。 C11 將會 zhhans 引入；zhhant 引進 外部模板這一 zhhans 概念；zhhant 構想；。C 已經有了強制編譯器在特定 zhhans 位置；zhhant 地點 開始具現化的語法： template class stdvectorMyClass 而 C 所缺乏的是阻止編譯器在某個編譯單元內具現化模板的能力。C11 將簡單 zhhans 地；zhhant 的 擴充前文語法如下： extern template class stdvectorMyClass 這樣就告訴編譯器不要在該編譯單元內將該模板具現化。 核心語言使用性的加強 這些特色存在的主要目的是為了使 C 能夠更容易使用。舉凡可以增進型別安全，減少程式碼重複，不易誤用程式碼之類的。 初始化列表 標準 C 從 C 帶來了初始化列表（initializer list）的概念。這個構想是結構或是陣列能夠依據成員在該結構內定義的順序透過給予的一串引數來產生。這些初始化列表是遞迴的，所以結構的陣列或是包含其他結構的結構可以使用它們。這對靜態列表或是僅是把結構初始化為某值而言相當有用。C 有建構函式，能夠重複物件的初始化。但單單只有那樣並不足以取代這項特色的所有機能。在 C03 中，只允許在嚴格遵守 POD 的定義和限制條件的結構及類別上使用這項機能，非 POD 的型別不能使用，就連相當有用的 STL 容器 stdvector 也不行。 C11 將會把初始化列表的概念綁到型別上，稱作 stdinitializer_list。這允許建構函式或其他函式像引數般地使用初始化列表。舉例來說： class SequenceClass public SequenceClass stdinitializer_listint list 這將允許 SequenceClass 由一連串的整數構造，就像： SequenceClass someVar 1 4 5 6 這個建構函式是種特殊的建構函式，稱作初始化列表建構函式。有著這種建構函式的類別在統一初始化的時候會被特別對待。 類別 stdinitializer_list 是個第一級的 C11 標準程式庫型別。然而他們只能夠經由 C11 編譯器透過 語法的使用被靜態地構造。這個列表一經構造便可複製，雖然這只是 copybyreference。初始化列表是常數；一旦被建立，其成員均不能被改變，成員中的資料也不能夠被變動。 因為初始化列表是真實型別，除了類別構造式之外還能夠被用在其他地方。正規的函式能夠使用初始化列表作為形參。例如： void FunctionName stdinitializer_listfloat list FunctionName 10f 345f 04f 標準容器也能夠以這種方式初始化： vectorstring v xyzzy plugh abracadabra vectorstring v xyzzy plugh abracadabra vectorstring v xyzzy plugh abracadabra 見下節 統一的初始化 統一的初始化 標準 C 在初始化型別方面有著許多問題。初始化型別有數種方法，而且交換使用時不會都產生相同結果。傳統的建構式語法，看起來像是函式宣告，而且為了能使編譯器不會弄錯必須採取一些步驟。只有集合體和 POD 型別能夠被集合式的初始化（使用 SomeType var stuff）。 C11 將會提供一種統一的語法初始化任意的物件，它擴充了初始化串列語法： struct BasicStruct int x float y struct AltStruct AltStruct int _x float _y x _x y _y private int x float y BasicStruct var1 5 32f AltStruct var2 2 43f var1 的初始化的運作就如同 Cstyle 的初始化串列。每個公開的變數將被對應於初始化串列的值給初始化。隱式型別轉換會在需要的時候被使用，這裡的隱式型別轉換不會產生範圍縮限（narrowing）。要是不能夠轉換，編譯便會失敗。（範圍縮限 （narrowing）：轉換後的型別無法表示原型別。如將 32bit 的整數轉換為 16bit 或 8bit 整數，或是浮點數轉換為整數。）var2 的初始化則是簡單地呼叫建構式。 統一的初始化建構能夠免除具體指定特定型別的必要： struct IdString stdstring name int identifier IdString var3 SomeName 4 該語法將會使用 const char 引數初始化 stdstring。你也可以做像下面的事： IdString GetString return SomeName 4 注意這裡不需要明確的型別 統一初始化不會取代建構式語法。仍然會有需要用到建構式語法的時候。如果一個類別擁有初始化列表建構函式（TypeName initializer_listSomeType），而初始化串列與建構函式的引數型別一致，那麼它比其他形式的建構式的優先權都來的高。C11 版本的 stdvector 將會有初始化串列建構式。這表示： stdvectorint theVec 4 這將會呼叫初始化串列建構式，而不是呼叫 stdvector 只接受一個尺寸引數產生相應尺寸 vector 的建構式。要使用這個建構式，使用者必須直接使用標準的建構式語法。 型別推導 在 C03 和 C，使用變數必須明確的指出其型別。然而，隨著模版型別的出現以及模板超程式設計的技巧，某物的型別，特別是函式定義明確的回返型別，就不容易表示。在這樣的情況下，將中間結果儲存於變數是件困難的事，可能會需要知道特定的超程式設計程式庫的內部情況。 C11 提供兩種方法緩解上述所遇到的困難。首先，有被明確初始化的變數可以使用 auto 關鍵字。對於指標型別，宣告為 auto 或者 auto 是一樣的。對於引用型別，必須使用 auto 。這會依據該初始化子（initializer）的具體型別產生變數： auto integralVariable 5 auto unsignedVariable 5UL auto ptrToObject new MyPackageObject 在上面的簡易例子中，程式設計師和編譯器都能輕易判斷出幾個變數的型別。而透過使用 UL 字尾，unsignedVariable 的型別自動成為 unsigned long。最後，動態建立物件時已經要在 new 後輸入型別，此時使用 auto 就能省略掉累贅的 MyPackageObject 宣告。 using namespace stdplaceholders auto someStrangeCallableType stdbind SomeFunction _2 _1 someObject auto otherVariable 5 上面的例子中說明 auto 有利於 C 支援函數語言程式設計。這裡注意 stdbind 也是 C11 從 Boost C Libraries 中引入的模版函式。stdbind 實現了偏函式，在上面的例子中它將函式 SomeFunction 的第三個引數繫結為 someObject，並將第一和第二個引數的在引數列表中的順序倒轉，由此生成一個函式物件 someStrangeCallableType。該函式物件的型別非常複雜，但編譯器卻能輕易地將其推匯出來。 除此之外，decltype 能夠被用來在編譯期決定一個表示式的型別。舉例： int someInt decltype someInt otherIntegerVariable 5 decltype 和 auto 一起使用會更為有用，因為 auto 變數的型別只有編譯器知道。然而 decltype 對於那些大量運用運運算元過載和特化的型別的程式碼的表示也非常有用。 auto 對於減少冗贅的程式碼也很有用。舉例而言，程式員不用寫像下面這樣： for vectorintconst_iterator itr myveccbegin itr myveccend itr 而可以用更簡短的 for auto itr myveccbegin itr myveccend itr 由於 myvec 實現了 beginend 迭代器，C11 提供了基於範圍的迴圈來大幅度省略程式碼。 for auto x myvec 這項差異隨著程式員開始巢狀容器而更為顯著，雖然在這種情況下 typedef 是一個減少程式碼的好方法。 decltype 所表示的型別可以和 auto 推匯出來的不同。 include vector int main const stdvectorint v 1 auto a v 0；a 為 int 型別 decltype（v 0 b 0 b 為 const int 型別，即 stdvectorintoperator （size_type）const 的回返型別 auto c 0 c 為 int 型別 auto d c d 為 int 型別 decltype c e e 為 int 型別，c 實體的型別 decltype c f e f 為 int 型別，因為（c）是左值 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 x my_array x 2 similar but also using type inference for array elements for auto x my_array x 2 上面 for 述句的第一部份定義被用來做範圍迭代的變數，就像被宣告在一般 for 迴圈的變數一樣，其作用域僅只於迴圈的範圍。而在 之後的第二區塊，代表將被迭代的範圍。這種 for 語句還可以用於 C 型陣列，初始化列表，和任何定義了 begin 和 end 來返回首尾迭代器的型別。 Lambda 函式與表示式 在標準 C，特別是當使用 C 標準程式庫演演算法函式諸如 sort 和 find，使用者經常希望能夠在演演算法函式呼叫的附近定義一個臨時的述部函式（又稱謂詞函式，predicate function）。由於語言本身允許在函式內部定義類別，可以考慮使用函式物件，然而這通常既麻煩又冗贅，也阻礙了程式碼的流程。此外，標準 C 不允許定義於函式內部的類別被用於模板，所以前述的作法是不可行的。 C11 對 lambda（即匿名函式）的支援可以解決上述問題。 一個 lambda 函式可以用如下的方式定義： int x int y return x y 這個不具名函式的回返型別是 decltype xy。只有在 lambda 函式符合 return expression 的形式下，它的回返型別才能被忽略。在前述的情況下，lambda 函式僅能為一個述句。 在一個更為複雜的例子中，回返型別可以被明確的指定如下： int x int y int int z x y return z x 本例中，一個暫時的變數 z 被建立用來儲存中間結果。如同一般的函式，z 的值不會保留到下一次該不具名函式再次被呼叫時。 如果 lambda 函式沒有傳回值（例如 void），其回返型別可被完全忽略。 定義在與 lambda 函式相同作用域的變數參考也可以被使用。這種的變數集合一般被稱作 closure（閉包）。 沒有定義任何變數。使用未定義變數會引發錯誤。 x y x 以傳值方式傳入（預設），y 以引用方式傳入。 任何被使用到的外部變數都隱式地以引用方式加以引用。 任何被使用到的外部變數都隱式地以傳值方式加以引用。 x x 顯式地以傳值方式加以引用。其餘變數以引用方式加以引用。 z z 顯式地以引用方式加以引用。其餘變數以傳值方式加以引用。 closure 被定義與使用如下： stdvectorint someList int total 0 stdfor_each someListbegin someListend totalint x total x stdcout total 上例可計算 someList 元素的總和並將其印出。變數 total 是 lambda 函式 closure 的一部分，同時它以引用方式被傳遞入謂詞函式，因此它的值可被 lambda 函式改變。 若不使用引用的符號 ，則代表變數以傳值的方式傳入 lambda 函式。讓使用者可以用這種表示法明確區分變數傳遞的方法：傳值，或是傳參考。由於 lambda 函式可以不在被宣告的地方就地使用（如置入 stdfunction 物件中）； 這種情況下，若變數是以傳參考的方式連結到 closure 中，是無意義甚至是危險的行為。 若 lambda 函式只在定義的作用域使用，則可以用 宣告 lambda 函式，代表所有引用到 stack 中的變數，都是以參考的方式傳入，不必一一顯式指明： stdvectorint someList int total 0 stdfor_each someListbegin someListend int x total x 變數傳入 lambda 函式的方式可能隨實做有所變化，一般期望的方法是 lambda 函式能保留其作用域函式的 stack 指標，藉此存取區域變數。 若使用 而非 ，則代表所有的參考的變數都是傳值使用。 對於不同的變數，傳值或傳參考可以混和使用。比方說，使用者可以讓所有的變數都以傳參考的方式使用，但帶有一個傳值使用的變數： int total 0 int value 5 valueint x total x value total 是傳參考的方式傳入 lambda 函式，而 value 則是傳值。 若一個 lambda 函式被定義於某類別的成員函式中，則可以使用該類別物件的參考，並且能夠存取其內部的成員。 SomeType typePtr typePtrSomePrivateMemberFunction 這只有當該 lambda 函式建立的作用域是在 SomeType 的成員函式內部時才能運作。 在成員函式中指涉物件的 this 指標，必須要顯式的傳入 lambda 函式，否則成員函式中的 lambda 函式無法使用任何該物件的變數或函式。 this thisSomePrivateMemberFunction 若是 lambda 函式使用 或是 的形式，this 在 lambda 函式即為可見。 lambda 函式是編譯器從屬型別的函式物件；這種型別名稱只有編譯器自己能夠使用。如果使用者希望將 lambda 函式作為引數傳入，該型別必須是模版型別，或是必須建立一個 stdfunction 去獲取 lambda 的值。使用 auto 關鍵字讓我們能夠儲存 lambda 函式： auto myLambdaFunc this thisSomePrivateMemberFunction auto myOnheapLambdaFunc new auto lambda 函式按照值方式捕獲的環境中的變數，是不能修改的。否則，編譯器會報錯：by copy capture cannot be modified in a nonmutable lambda。其值是 lambda 函式定義時捕獲的值，不再改變。如果在 lambda 函式定義時加上 mutable 關鍵字，則該捕獲的傳值變數是可以修改的，對同一個 lambda 函式的隨後呼叫也會累加影響該捕獲的傳值變數，但對外界環境中被捕獲的那個變數無影響。例如： include iostream 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 變得更為複雜時，它暴露出許多語法上的限制，特別是針對函式模板的宣告。下面的範例，不是合法的 C03： templatetypename LHS typename RHS Ret AddingFunc const LHS lhs const RHS rhs return lhs rhs Ret 的型別必須是 lhsrhs 的型別 Ret 的型別由 LHS 與 RHS 相加之後的結果的型別來決定。即使使用 C11 新加入的 decltype 來宣告 AddingFunc 的返回型別，依然不可行。 templatetypename LHS typename RHS decltype lhsrhs AddingFunc const LHS lhs const RHS rhs return lhs rhs 不合法的 C11 不合法的原因在於 lhs 及 rhs 在定義前就出現了。直到剖析器解析到函式原型的後半部，lhs 與 rhs 才是有意義的。 針對此問題，C11 引進一種新的函式定義與宣告的語法： templatetypename LHS typename RHS auto AddingFunc const LHS lhs const RHS rhs decltype lhsrhs return lhs rhs 這種語法也能套用到一般的函式定義與宣告： struct SomeStruct auto FuncName int x int y int auto SomeStructFuncName int x int y int return x y 關鍵字 auto 的使用與其在自動型別推導代表不同的意義。 物件建構的改良 在 C03 中，建構式不能呼叫其它的建構式；每個建構式必須自己初始化所有的成員或是呼叫一個共用的成員函式。基礎類別的建構式不能夠直接作為衍生類別的建構式；就算基類的建構式已經足夠，每個衍伸的類別仍必須實做自己的建構式。類別中 nonconstant 的資料成員不能夠在宣告的地方被初始化，它們只能在建構式中被初始化。 C11 將會提供這些問題的解決方案。 C11 允許建構式呼叫其他建構式，這種做法稱作委託（delegation）構造。僅僅只需要加入少量的程式碼，就能讓數個建構式之間達成功能復用（reuse）。Java 以及 C都有提供這種功能。C11 語法如下： class SomeType int number string name SomeType int i string s number i name s public SomeType SomeType 0 invalid SomeType int i SomeType i guest SomeType string s SomeType 1 sPostInit class DCExcept public DCExcept double d try DCExcept 1 dcout run the body endl catch cout caught exceptionendl private DCExcept int i double d cout going to throw endl throw 0 int type double date C03 中，建構式執行結束代表物件建構完成； 而允許使用轉接建構式的 C11 則是以 任何 一個建構式結束代表建構完成。使用委託的建構式，函式本體中的程式碼將於被委託的建構式完成後繼續執行（如上例的 PostInit ）。若基類使用了委託建構式，則衍生類別的建構式會在 所有 基底類別的建構式都完成後，才會開始執行。 C11 允許衍生類別手動繼承基底類別的建構式，編譯器可以使用基底類別的建構式完成衍生類別的建構。而將基類的建構式帶入衍生類的動作，無法選擇性地部分帶入，要不就是繼承基類全部的建構式，要不就是一個都不繼承（不手動帶入）。此外，若牽涉到多重繼承，從多個基底類別繼承而來的建構式不可以有相同的函式簽名（signature）。而衍生類別的新加入的建構式也不可以和繼承而來的基底建構式有相同的函式簽名，因為這相當於重複宣告。 語法如下： class BaseClass public BaseClass int iValue class DerivedClass public BaseClass public using BaseClassBaseClass 此語法等同於 DerivedClass 宣告一個 DerivedClass int 的建構式。同時也因為 DerivedClass 有了一個繼承而來的建構式，所以不會有預設建構式。 另一方面，C11 可以使用以下的語法完成資料成員的原地（inplace 初始化： class SomeClass public SomeClass explicit SomeClass int iNewValue iValue iNewValue private int iValue 5 若是建構式中沒有設定 iValue 的初始值，則會採用類別定義中的成員初始化，令 iValue 初值為 5。在上例中，無引數版本的建構式，iValue 便採用預設所定義的值；而帶有一個整數引數的建構式則會以指定的值完成初始化。 成員初始化除了上例中的賦值形式（使用 ），也可以採用建構式以及統一形的初始化（uniform initialization，使用 ）。 顯式虛擬函式過載 在 C 裡，在子類別中容易意外的過載虛擬函式。舉例來說： struct Base virtual void some_func struct Derived Base void some_func Derivedsome_func 的真實意圖為何？程式設計師真的試圖過載該虛擬函式，或這只是意外？這也可能是 base 的維護者在其中加入了一個與 Derivedsome_func 同名且擁有相同簽名的虛函式。 另一個可能的狀況是，當基類中的虛函式的簽名被改變，子類中擁有舊簽名的函式就不再過載該虛函式。因此，如果程式設計師忘記修改所有子類，執行期將不會正確呼叫到該虛函式正確的實現。 C11 將加入支援用來防止上述情形產生，並在編譯期而非執行期捕獲此類錯誤。為保持向後相容，此功能將是選擇性的。其語法如下： struct Base virtual void some_func float struct Derived Base virtual void some_func int override 錯誤格式：Derivesome_func 並沒有 override Basesome_func virtual void some_func float override OK：顯式改寫 編譯器會檢查基底類別是否存在一虛擬函式，與衍生類別中帶有宣告 override 的虛擬函式，有相同的函式簽名（signature）；若不存在，則會回報錯誤。 C11 也提供指示字 final，用來避免類別被繼承，或是基底類別的函式被改寫： struct Base1 final struct Derived1 Base1 錯誤格式：class Base1 已標明為 final struct Base2 virtual void f final struct Derived2 Base2 void f 錯誤格式：Base2f 已標明為 final 以上的範例中，virtual void f final 宣告一新的虛擬函式，同時也表明禁止衍生函式改寫原虛擬函式。 override 與 final 都不是語言關鍵字（keyword），只有在特定的位置才有特別含意，其他地方仍舊可以作為一般指示字（identifier）使用。 空指標 早在 1972 年，C 語言誕生的初期，常數 0 帶有常數及空指標的雙重身分。 C 使用 preprocessor macro NULL 表示空指標，讓 NULL 及 0 分別代表空指標及常數 0。 NULL 可被定義為 void 0 或是 0。 C 並不採用 C 的規則，不允許將 void 隱式轉換為其他型別的指標。為了使程式碼 char c NULL 能透過編譯，NULL 只能定義為 0。這樣的決定使得函式多載無法區分程式碼的語意： void foo char void foo int void foo nullptr_t C 建議 NULL 應當定義為 0，所以 foo NULL 將會呼叫 foo int，這並不是程式設計師想要的行為，也違反了程式碼的直觀性。0 的歧義在此處造成困擾。 C11 引入了新的關鍵字來代表空指標常數：nullptr，將空指標和整數 0 的概念拆開。 nullptr 的型別為 nullptr_t，能隱式轉換為任何指標或是成員指標的型別，也能和它們進行相等或不等的比較。而 nullptr 不能隱式轉換為整數，也不能和整數做比較。 為了向下相容，0 仍可代表空指標常數。 char pc nullptr OK int pi nullptr OK int i nullptr error bool b nullptr OK foo pc 呼叫 foo char 而不是 foo int foo nullptr 呼叫 foo nullptr_t 值得注意的是上面的 foo nullptr_t 被隱式轉換為 foo char 只會發生在該函式不存在其它的指標型別過載（比如 foo int foo MyClass 等）時候，否則就會產生歧義錯誤（可以透過顯示宣告一個 foo nullptr_t 來消除該歧義）。 在 C11 的標準型別標頭檔案中，nullptr_t 型別應該被宣告為： typedef decltype nullptr nullptr_t 而不是： typedef int nullptr_t C11 之前的標準需要定義 NULL 為 0 typedef void nullptr_t ANSI C 定義 NULL 為 void 0 強型別列舉 在 C03 中，列舉型別不是型別安全的。列舉型別被視為整數，這使得兩種不同的列舉型別之間可以進行比較。C03 唯一提供的安全機制是一個整數或一個列舉型值不能隱式轉換到另一個列舉別型。此外，列舉所使用整數型別及其大小都由實作方法定義，皆無法明確指定。最後，列舉的名稱全數暴露於列舉型別的作用域中，因此兩個不同的列舉，不可以有相同的列舉名。（好比 enum Side Right Left 和 enum Thing Wrong Right 不能一起使用。） C11 引進了一種特別的 列舉類，可以避免上述的問題。使用 enum class 的語法來宣告： enum class myEnumeration Val1 Val2 Val3 100 Val4 101 此種列舉為型別安全的。列舉類別不能隱式地轉換為整數；也無法與整數數值做比較。（表示式 EnumerationVal4 101 會觸發編譯期錯誤）。 列舉類別所使用型別必須顯式指定。在上面的範例中，使用的是預設型別 int，但也可以指定其他型別： enum class Enum2 unsigned int Val1 Val2 列舉類別的作用域（scoping）不包含列舉值的名字。使用列舉值的名字，必須明確限定於其所屬的列舉型別。例如，前述列舉類別 Enum2，Enum2Val1 是有意義的表示法，而單獨的 Val1 則否。 此外，C11 允許為傳統的列舉指定使用型別： enum Enum3 unsigned long Val1 1 Val2 列舉名 Val1 定義於 Enum3 的列舉範圍中（Enum3Val1），但為了向後相容性， Val1 仍然可以於所屬列舉型別所在的作用域中單獨使用。 在 C11 中，列舉類別的前置宣告（forward declaration）也是可行的，只要使用可指定型別的新式列舉即可。之前的 C 無法寫出列舉的前置宣告，是由於無法確定列舉變數所佔的空間大小，C11 解決了這個問題： enum Enum1 C 與 C11 中不合法；無法判別大小 enum Enum2 unsigned int 合法的 C11 enum class Enum3 合法的 C11，列舉類別使用預設型別 int enum class Enum4 unsigned int 合法的 C11 enum Enum2 unsigned short 不合法的 C11，Enum2 已被宣告為 unsigned int 角括號 C03 的剖析器一律將 視為右移運運算元。但在巢狀樣板定義式中，絕大多數的場合其實都代表兩個連續右角括號。為了避免剖析器誤判，撰碼時不能把右角括號連著寫。 C11 變更了剖析器的解讀規則；當遇到連續的右角括號時，會在合理的情況下將右尖括號解析為樣板引數的結束符號。給使用 的表示式加上圓括號，可以避免其與圓括號外部的左尖括號相匹配： templatebool bTest class SomeType stdvectorSomeType12 x1 解讀為 stdvector of SomeTypetrue 2， 非法的表示式，整數 1 被轉換為 bool 型別 true stdvectorSomeType12 x1 解讀為 stdvector of SomeTypefalse 合法的 C11 表示式，12 被轉換為 bool 型別 false 顯式型別轉換子 C98 引入了關鍵字 explicit 來避免使用者自定的單引數建構式被當成隱式型別轉換子。但是，卻沒有限制明確定義的型別轉換函式。比方說，一個 smart pointer 類別具有一個 operator bool ，被定義成若該 smart pointer 不為 null 則傳回 true，反之傳回 false。遇到這樣的程式碼時：if smart_ptr_variable，編譯器可以藉由 operator bool 隱式轉換成布林值，和測試原生指標的方法一樣。但是這類隱式轉換同樣也會發生在非預期之處。由於 C 的 bool 型別也是算術型別，能隱式換為整數甚至是浮點數。拿物件轉換出的布林值做布林運算以外的數學運算，往往不是程式設計師想要的。 在 C11 中，關鍵字 explicit 修飾符也能套用到型別轉換函式上。如同建構式一樣，它能避免型別轉換函式被隱式轉換呼叫。但 C11 特別指定，在 if 條件式、迴圈、邏輯運算等需要布林值的地方，將其作為顯式型別轉換，因此即使對應的型別轉換函式被 explicit 修飾也可以呼叫。這主要為了解決 safe bool 問題。 模板的別名 在進入這個主題之前，各位應該先弄清楚「模板」和「型別」本質上的不同。class template 類別模板，是模板 是用來產生 template class（模板類別，是型別）。在 C03 中，typedef 可定義模板類別一個新的型別名稱，但是不能夠使用 typedef 來定義模板的別名。舉例來說： templatetypename first typename second int third class SomeType templatetypename second typedef SomeTypeOtherType second 5 TypedefName 在 C03 是不合法的 這不能夠透過編譯。 為了定義模板的別名，C11 將會增加以下的語法： templatetypename first typename second int third class SomeType templatetypename second using TypedefName SomeTypeOtherType second 5 using 也能在 C11 中定義一般型別的別名，等同 typedef： typedef void PFDdouble 傳統語法 using PFD void double 新增語法 模板引數的預設值 C98 支援類模板的模板引數預設值，不支援函式模板的模板引數預設值。C11 可以支援函式模板的模板引數預設值。類模板的模板引數預設值需要從右到左依次出現；函式模板的預設模板引數沒有此約束。 void DefParm int m 3 c98 編譯透過，c11 編譯透過 template typename T int class DefClass c98 編譯透過，c11 編譯透過 template typename T int void DefTempParm c98 編譯失敗，c11 編譯透過 以下為 C11 編譯： template typename T1 typename T2 int class DefClass1 template typename T1 int typename T2 class DefClass2 ERROR 無法透過編譯：因為模板引數的預設值沒有遵循 由右往左 的規則 template typename T int i 0 class DefClass3 template int i 0 typename T class DefClass4 ERROR 無法透過編譯：因為模板引數的預設值沒有遵循 由右往左 的規則 template typename T1 int typename T2 void DefFunc1 T1 a T2 b OK 函式模板不用遵循 由右往左 的規則 template int i 0 typename T void DefFunc2 T a OK 函式模板不用遵循 由右往左 的規則 通常，如果能夠從函式實參中推匯出型別的話，那麼預設模板引數就不會被使用，反之，預設模板引數則可能會被使用： template class T class U double void f T t 0 U u 0 void g f 1 c fint char1 c f 1 fint double1 0 使用了預設模板引數 double f 錯誤 T 無法被推匯出來 fint fint double0 0 使用了預設模板引數 double fint char fint char0 0 無限制的 unions 在 C03 中，並非任意的型別都能做為 union 的成員。比方說，帶有 nontrivial 建構式的型別就不能是 union 的成員。在新的標準裡，移除了所有對 union 的使用限制，除了其成員仍然不能是引用型別。這一改變使得 union 更強大，更有用，也易於使用。 但是如果 union 成員具有非平凡的特殊成員函式，則編譯器不會為 union 生成對應的特殊成員函式，必須手工定義。 以下為 C11 中 union 使用的簡單範例： struct Point Point Point int x int y x_x y_y int x_ y_ union U int z double w Point p 在 C03 中是不合法（point 有一 nontrivial 建構式），但是在 C11 是合法的 U 由於 Point 成員的存在，必須要定義一個建構函式 U const Point pt p pt 透過初始化列表構造 Point 物件 U operatorconst Point pt new p Point pt return this 透過原地 new 方式賦值構造 Point 物件 這一改變僅放寬 union 的使用限制，不會影響既有的舊程式碼。 核心語言能力的提升 這些特性讓 C 語言能夠做一些以前做不到的，或者極其複雜的，或者需求一些不可移植的庫的事情。 可變引數模板 在 C11 之前，不論是類模板或是函式模板，都只能按其被宣告時所指定的樣子，接受一組固定數目的模板引數；C11 加入新的表示法，允許任意長度、任意型別的模板引數，不必在定義時將引數的個數固定。 templatetypename Values class tuple 模板類 tuple 的物件，能接受不限個數的 typename 作為它的模板引數： class tupleint stdvectorint stdmapstdstring stdvectorint someInstanceName zhhans 實參；zhhant 引數 的個數也可以是 0，所以 class tuple someInstanceName 這樣的定義也是可以的。 若不希望產生 zhhans 實參；zhhant 引數 個數為 0 的不定長引數模板，則可以採用以下的定義： templatetypename First typename Rest class tuple 不定長引數模板也能運用到模板函式上。傳統 C 中的 printf 函式，雖然也能達成不定長度的引數的呼叫，但其並非型別安全。以下的範例中，C11 除了能定義型別安全的不定長引數函式外，還能讓類似 printf 的函式能自然地處理非內建型別的物件。除了在模板引數中能使用 表示不定長模板引數外，函式引數也使用同樣的表示法代表不定長引數。 templatetypename Params void printf const stdstring strFormat Params parameters 其中，Params 與 parameters 分別代表模板與函式的不定長引數集合，稱之為引數包（parameter pack）。引數包必須要和運算元 搭配使用，避免語法上的歧義。 不定長引數模板中，不定長引數包無法如同一般引數在類或函式中使用； 因此典型的手法是以遞迴的方法取出可用引數，參看以下的 C11 printf 範例： void printf const char s while s if s s throw stdruntime_error invalid format string missing arguments stdcout s templatetypename T typename Args void printf const char s T value Args args while s if s s stdcout value printf s s s args 即便當 s 0 也會產生呼叫，以檢測更多的型別引數。 return stdcout s throw stdlogic_error extra arguments provided to printf printf 會不斷地遞迴呼叫自身：函式引數包 args 在呼叫時，會被模板型別匹配分離為 T value 和 Args args。直到 args 變為空引數，則會與簡單的 printf const char s 形成匹配，結束遞迴。 另一個例子為計算模板引數的長度，這裡使用相似的技巧展開模板引數包 Args： templatetypename args struct Count template struct count static const int value 0 templatetypename T typename Args struct countT Args static const int value 1 countArgsvalue zhhans 雖然沒有一個簡潔的機制能夠對變長引數模板中的值進行迭代；zhhant 雖然沒有很簡單的機制能個別依序處理變長引數模板的引數，但使用運算元 還能在程式碼各處對引數包施以更複雜的展開操作。舉例來說，一個模板類的定義： template typename BaseClasses class ClassName public BaseClasses public ClassName BaseClasses baseClasses BaseClasses baseClasses BaseClasses 會被展開成類別 ClassName 的基底類；ClassName 的建構式需要所有基底類的右值引用，而每一個基底類都是以傳入的引數做初始化（BaseClasses baseClasses）。 在函式模板中，不定長引數可以和右值參照搭配，達成引數的完美轉送（perfect forwarding）： templatetypename TypeToConstruct struct SharedPtrAllocator templatetypename Args stdshared_ptrTypeToConstruct ConstructWithSharedPtr Args params return stdshared_ptrTypeToConstructnew TypeToConstruct stdforwardArgsparams 引數包 parms 可展開為 TypeToConstruct 建構式的引數。表示式 stdforwardArgsparams 可將引數的型別資訊保留（利用右值參照），傳入建構式。而運算元 則能將前述的表示式套用到每一個引數包中的引數。這種工廠函式（factory function）的手法，使用 stdshared_ptr 管理配置物件的記憶體，避免了不當使用所產生的記憶體洩漏（memory leaks）。 此外，不定長引數的數量可以藉以下的語法得知： templatetypename Args struct SomeStruct static const int size sizeofArgs SomeStructType1 Type2size 是 2，而 SomeStructsize 會是 0。（sizeofArgs 的結果是編譯期常數。） 新的字串字面值 標準 C 提供了兩種字串字面值。第一種，包含有雙引號，產生以空字元結尾的 const char 陣列。第二種有著前標 L，產生以空字元結尾的 const wchar_t 陣列，其中 wchar_t 代表寬字元。對於 Unicode 編碼的支援尚付闕如。 為了加強 C 編譯器對 Unicode 的支援，型別 char 的定義被修改為其大小至少能夠儲存 UTF8 的 8 位元編碼，並且能夠容納編譯器的基本字元集的任何成員。 C11 將支援三種 Unicode 編碼方式：UTF8，UTF16，和 UTF32。除了上述 char 定義的變更，C11 將增加兩種新的字元型別：char16_t 和 char32_t。它們各自被設計用來儲存 UTF16 以及 UTF32 的字元。 以下展示如何產生使用這些編碼的字串字面值： u8Im a UTF8 string uThis is a UTF16 string UThis is a UTF32 string 第一個字串的型別是通常的 const char ；第二個字串的型別是 const char16_t ；第三個字串的型別是 const char32_t 。 當建立 Unicode 字串字面值時，可以直接在字串內插入 Unicode codepoints。C11 提供了以下的語法： u8This is a Unicode Character u2018 uThis is a bigger Unicode Character u2018 UThis is a Unicode Character U00002018 在 u 之後的是 16 個位元的十六進位數值；它不需要 0x 的前標。識別字 u 代表了一個 16 位元的 Unicode codepoint；如果要輸入 32 位元的 codepoint，使用 U 和 32 個位元的十六進位數值。只有有效的 Unicode codepoints 能夠被輸入。舉例而言，codepoints 在範圍 UD800UDFFF 之間是被禁止的，它們被保留給 UTF16 編碼的 surrogate pairs。 有時候避免手動將字串換碼也是很有用的，特別是在使用 XML 檔案或是一些指令碼語言的字面值的時候。C11 將提供 raw（原始）字串字面值： RThe String Data StuffRdelimiter The String Data Stuff delimiter 在第一個例子中，任何包含在 括號（標準已經從 改為 ）當中的都是字串的一部分。其中 和 字元不需要經過轉義。在第二個例子中，delimiter 開始字串，只有在遇到 delimiter才代表結束。其中 delimiter 可以是最多 16 個字元的任意的字串（包含空字串），但不能包含空格、控制字元和 、、。原始字串允許使用者使用圓括號 ，例如 Rdelimiter az delimiter等價於az。原始字串字面值能夠和寬字面值或是 Unicode 字面值結合： u8RXXX Im araw UTF8string XXX uRThis is araw UTF16string visual studio not support uRThis is araw UTF16string URThis is araw UTF32string 使用者定義字面量 標準 C 提供了數種字面值。字元 125 是能夠被編譯器解釋為數值 125 的 double 型別字面值。然而，加上 f 的後置，像是 125f，則會產生數值為 125 的 float 型別字面值。之前的 C 規範中字面值的修飾符是固定的，C 程式碼不能創立新的字面修飾符。 C11 開放使用者定義新的字面修飾符（literal modifier），利用自訂的修飾符完成由字面值建構物件。 字面值轉換可以定義為兩個階段：原始與轉換後（raw 與 cooked）。原始字面值指特定型別的字元序列，而轉換後的字面值則代表另一種型別。如字面值 1234，原始字面值是 1 2 3 4 的字元序列；而轉換後的字面值是整數值 1234。另外，字面值 0xA 轉換前是序列 0 x A；轉換後代表整數值 10。 多工記憶體模型 C 標準委員會計劃統一對多緒程式設計的支援。 這將涉及兩個部分：第一、設計一個可以使多個執行緒在一個程序中共存的記憶體模型；第二、為執行緒之間的互動提供支援。第二部分將由程式庫提供支援，更多請看緒程支援。 在多個執行緒可能會訪問相同記憶體的情形下，由一個記憶體模型對它們進行排程是非常有必要的。遵守模型規則的程式是被保證正確執行的，但違反規則的程式會發生不可預料的行為，這些行為依賴於編譯器的最佳化和記憶體一致性的問題。 threadlocal 的儲存期限 在多緒環境下，讓各緒程擁有各自的變數是很普遍的。這已經存在於函式的區域變數，但是對於全域和靜態變數都還不行。 新的 thread_local 儲存期限（在現行的 static、dynamic 和 automatic 之外）被作為下個標準而提出。緒程區域的儲存期限會藉由儲存指定字 thread_local 來表明。 static 物件 生命週期為整個程式的執行期間 的儲存期限可以被 threadlocal 給替代。就如同其他使用 static 儲存期的變數，threadlocal 物件能夠以建構式初始化並以解構式摧毀。 使用或停用物件的預設函式 在傳統 C 中，若使用者沒有提供，則編譯器會自動為物件生成預設建構式 default constructor、複製建構式（copy constructor），賦值運運算元（copy assignment operator operator）以及解構式（destructor）。另外，C 也為所有的類別定義了數個全域運算元（如 operator delete 及 operator new）。當使用者有需要時，也可以提供自訂的版本改寫上述的函式。 問題在於原先的 c 無法精確地控制這些預設函式的生成。比方說，要讓類別不能被複製，必須將複製建構式與賦值運運算元宣告為 private，並不去定義它們。嘗試使用這些未定義的函式會導致編譯期或連結期的錯誤。但這種手法並不是一個理想的解決方案。 此外，編譯器產生的預設建構式與使用者定義的建構式無法同時存在。若使用者定義了任何建構式，編譯器便不會生成預設建構式； 但有時同時帶有上述兩者提供的建構式也是很有用的。目前並沒有顯式指定編譯器產生預設建構式的方法。 C11 允許顯式地表明採用或拒用編譯器提供的內建函式。例如要求類別帶有預設建構式，可以用以下的語法： struct SomeType SomeType default 預設建構式的顯式宣告 SomeType OtherType value 另一方面，也可以禁止編譯器自動產生某些函式。如下面的例子，類別不可複製： struct NonCopyable NonCopyable operatorconst NonCopyable delete NonCopyable const NonCopyable delete NonCopyable default 禁止類別以 operator new 配置記憶體： struct NonNewable void operator new stdsize_t delete 此種物件只能生成於 stack 中或是當作其他類別的成員，它無法直接配置於 heap 之中，除非使用了與平臺相關，不可移植的手法。（使用 placement new 運算元雖然可以在使用者自配置的記憶體上呼叫物件建構式，但在此例中其他形式的 new 運算元一併被上述的定義遮蔽（name hiding），所以也不可行。） delete 的宣告（同時也是定義）也能適用於非內建函式，禁止成員函式以特定的引數呼叫： struct NoDouble void f int i void f double delete 若嘗試以 double 的引數呼叫 f ，將會引發編譯期錯誤，編譯器不會自動將 double 引數轉型為 int 再呼叫 f 。若要徹底的禁止以非 int 的引數呼叫 f ，可以將 delete 與模板相結合： struct OnlyInt void f int i templateclass T void f T delete long long int 型別 在 32 位元系統上，一個 long long int 是保有至少 64 個有效位元的整數型別。C99 將這個型別引入了標準 C 中，目前大多數的 C 編譯器也支援這種型別。C11 將把這種型別新增到標準 C 中。 靜態 assertion C 提供了兩種方法測試 assertion（宣告）：巨集 assert 以及前處理器指令 error。但是這兩者對於模版來說都不合用。巨集在執行期測試 assertion，而前處理器指令則在前置處理時測試 assertion，這時候模版還未能具現化。所以它們都不適合來測試牽扯到模板引數的相關特性。 新的機能會引進新的方式可以在編譯期測試 assertion，只要使用新的關鍵字 static_assert。宣告採取以下的形式： static_assert constantexpression errormessage 這裡有一些如何使用 static_assert 的例子： static_assert 314 GREEKPI GREEKPI 315 GREEKPI is inaccurate templateclass T struct Check static_assert sizeof int sizeof T T is not big enough 當常數表示式值為 false 時，編譯器會產生相應的錯誤訊息。第一個例子是前處理器指令 error 的替代方案；第二個例子會在每個模板類別 Check 生成時檢查 assertion。 靜態 assertion 在模板之外也是相當有用的。例如，某個演演算法的實作依賴於 long long 型別的大小比 int 還大，這是標準所不保證的。這種假設在大多數的系統以及編譯器上是有效的，但不是全部。 允許 sizeof 運運算元作用在類別的資料成員上，無須明確的物件 C98 sizeof 只能對例項的變數或者類的靜態成員進行操作，不能對類的非靜態成員進行操作，若要想達成對類的非靜態成員的操作，可以用如下 ugly 方式，0 強轉成物件的指標，並解析訪問對應非靜態成員變數。 struct SomeType OtherType member sizeof SomeType 0 member C98 sizeof SomeTypemember 直接由 SomeType 型別取得非靜態成員的大小，C03 不行。C11 允許 這會傳回 OtherType 的大小。C03 並不允許這樣做，所以會引發編譯錯誤。C11 將會允許這種使用。 垃圾回收機制 是否會自動回收那些無法被使用到（unreachable）的動態分配物件由實作決定。 參見 memory 標頭檔案中的幾個函式： void declare_reachable void p templateclass T T undeclare_reachable T p noexcept void declare_no_pointers charp size_t n noexcept void undeclare_no_pointers charp size_t n noexcept C 標準程式庫的變更 C11 標準程式庫有數個新機能。其中許多可以在現行標準下實作，而另外一些則依賴於（或多或少）新的 C11 核心語言機能。 新的程式庫的大部分被定義於 C 標準委員會的 Library Technical Report（稱 TR1），於 2005 年發布。各式 TR1 的完全或部分實作目前提供在名稱空間 stdtr1。C11 會將其移置於名稱空間 std 之下。 標準庫元件上的升級 目前的標準庫能受益於 C11 新增的一些語言特性。舉例來說，對於大部份的標準庫容器而言，像是搬移內含大量元素的容器，或是容器之內對元素的搬移，基於右值引用（Rvalue reference）的 move 建構子都能最佳化前述動作。在適當的情況下，標準庫元件將可利用 C11 的語言特性進行升級。這些語言特性包含但不侷限以下所列： 右值引用和其相關的 move 支援 支援 UTF16 編碼，和 UTF32 字元集 變長引數模板（與右值引用搭配可以達成完美轉發（perfect forwarding）） 編譯期常數表示式 Decltype 顯式型別轉換子 使用或停用物件的預設函式 此外，自 C 標準化之後已經過許多年。現有許多程式碼利用到了標準庫；這同時揭露了部份的標準庫可以做些改良。其中之一是標準庫的記憶體配置器（allocator）。C11 將會加入一個基於作用域模型的記憶體配置器來支援現有的模型。 執行緒支援 雖然 C11 會在語言的定義上提供一個記憶體模型以支援執行緒，但執行緒的使用主要將以 C11 標準函式庫的方式呈現。 C11 標準函式庫會提供類別 thread（stdthread）。若要執行一個執行緒，可以建立一個類別 thread 的實體，其初始引數為一個函式物件，以及該函式物件所需要的引數。透過成員函式 stdthreadjoin 對執行緒會合的支援，一個執行緒可以暫停直到其它執行緒執行完畢。若有底層平臺支援，成員函式 stdthreadnative_handle 將可提供對原生執行緒物件執行平臺特定的操作。 對於執行緒間的同步，標準函式庫將會提供適當的互斥鎖（像是 stdmutex，stdrecursive_mutex 等等）和條件變數（stdcondition_variable 和 stdcondition_variable_any）。前述同步機制將會以 RAII 鎖（stdlock_guard 和 stdunique_lock）和鎖相關演演算法的方式呈現，以方便程式員使用。 對於要求高效能，或是極底層的工作，有時或甚至是必須的，我們希望執行緒間的通訊能避免互斥鎖使用上的開銷。以原子操作來存取記憶體可以達成此目的。針對不同情況，我們可以透過顯性的記憶體屏障改變該存取記憶體動作的可見性。 對於執行緒間非同步的傳輸，C11 標準函式庫加入了以及 stdpackaged_task 用來包裝一個會傳回非同步結果的函式呼叫。因為缺少結合數個 future 的功能，和無法判定一組 promise 集合中的某一個 promise 是否完成，futures 此一提案因此而受到了批評。 更高階的執行緒支援，如執行緒池，已經決定留待在未來的 Technical Report 加入此類支援。更高階的執行緒支援不會是 C11 的一部份，但設想是其最終實現將建立在目前已有的執行緒支援之上。 stdasync 提供了一個簡便方法以用來執行執行緒，並將執行緒繫結在 stdfuture。使用者可以選擇一個工作是要多個執行緒上非同步的執行，或是在一個執行緒上執行並等待其所需要的資料。預設的情況，實作可以根據底層硬體選擇前面兩個選項的其中之一。另外在較簡單的使用情形下，實作也可以利用執行緒池提供支援。 多元組型別 多元組是一個內由數個異質物件以特定順序排列而成的資料結構。多元組可被視為是 struct 其資料成員的一般化。 由 TR1 演進而來的 C11 多元組型別將受益於 C11 某些特色像是可變引數模板。TR1 版本的多元組型別對所能容納的物件個數會因實作而有所限制，且實作上需要用到大量的巨集技巧。相反的，C11 版本的多元組型基本上於對其能容納的物件個數沒有限制。然而，編譯器對於模板實體化的遞迴深度上的限制仍舊影響了元組型別所能容納的物件個數（這是無法避免的情況）；C11 版本的多元組型不會把這個值讓使用者知道。 使用可變引數模板，多元組型別的宣告可以長得像下面這樣： template class Types class tuple 底下是一個多元組型別的定義和使用情況： typedef stdtuple int double long const char test_tuple long lengthy 12 test_tuple proof 18 65 lengthy Ciao lengthy stdget0proof 將 proof 的第一個元素賦值給 lengthy（索引從零開始起跳） stdget3proof Beautiful 修改 proof 的第四個元素 我們可以定義一個多元組型別物件 proof 而不指定其內容，前提是 proof 裡的元素其型別定義了預設建構子（default constructor）。此外，以一個多元組型別物件賦值給另一個多元組型別物件是可能的，但只有在以下情況：若這兩個多元組型別相同，則其內含的每一個元素其型別都要定義複製建構子（copy constructor）；否則的話，賦值運算子右邊的多元組其內含元素的型別必須能轉換成左邊的多元組其對應的元素型別，又或者賦值運算子左邊的多元組其內含元素的型別必須定義適當的建構子。 stdtupleint double string t1 stdtuplechar short const char t2 X 2 Hola t1 t2 可行。前兩個元素會作型別轉換， 第三個字串元素可由 const char 所建構。 多元組型別物件的比較運算是可行的（當它們擁有同樣數量的元素）。此外，C11 提供兩個表示式用來檢查多元組型別的一些特性（僅在編譯期做此檢查）。 stdtuple_sizeTvalue 回傳多元組 T 內的元素個數， stdtuple_elementI Ttype 回傳多元組 T 內的第 I 個元素的型別 雜湊表 在過去，不斷有要求想將雜湊表（無序關聯式容器）引進標準庫。只因為時間上的限制，雜湊表才沒有被標準庫所採納。雖然，雜湊表在最糟情況下（如果出現許多衝突（collision）的話）在效能上比不過平衡樹。但實際運用上，雜湊表的表現則較佳。 因為標準委員會還看不到有任何機會能將開放定址法標準化，所以目前衝突僅能透過鏈地址法（linear chaining）的方式處理。為避免與第三方函式庫發展的雜湊表發生名稱上的衝突，字首將採用 unordered 而非 hash。 函式庫將引進四種雜湊表，其中差別在於底下兩個特性：是否接受具相同鍵值的專案（Equivalent keys），以及是否會將鍵值對映到相對應的資料（Associated values）。 雜湊表型別 有無關聯值 接受相同鍵值 stdunordered_set stdunordered_multiset stdunordered_map stdunordered_multimap 上述的類別將滿足對一個容器類別的要求，同時也提供存取其中元素的成員函式：insert，erase，begin，end。 雜湊表不需要對現有核心語言做擴充套件（雖然雜湊表的實作會利用到 C11 新的語言特性），只會對標頭檔 functional 做些許擴充套件，並引入 unordered_set 和 unordered_map 兩個標頭檔。對於其它現有的類別不會有任何修改。同時，雜湊表也不會依賴其它標準庫的擴充套件功能。 正規表示式 過去許多或多或少標準化的程式庫被建立用來處理正規表示式。有鑑於這些演演算法的使用非常普遍，因此標準程式庫將會包含他們，並使用各種物件導向語言的潛力。 這個新的程式庫，被定義於 regex 標頭檔，由幾個新的類別所組成： 正規表示式（樣式）以樣板類 basic_regex 的實體表示 樣式匹配的情況以樣板類 match_results 的實體表示 函式 regex_search 是用來搜尋樣式；若要搜尋並取代，則要使用函式 regex_replace，該函式會回傳一個新的字串。演演算法 regex_search 和 regex_replace 接受一個正規表示式（樣式）和一個字串，並將該樣式匹配的情況儲存在 struct match_results。 底下描述了 match_results 的使用情況： const char reg_esp tn 分隔字元列表 stdregex rgx reg_esp regex 是樣板類 basic_regex 以型別為 char 的引數具現化的實體 stdcmatch match cmatch 是樣板類 match_results 以型別為 const char 的引數具現化的實體 const char target Polytechnic University of Turin 辨別所有被分隔字元所分隔的字 if regex_search target match rgx 若此種字存在 const size_t n matchsize for size_t a 0 a n a string str match afirst match asecond cout str n 注意雙反斜線的使用，因為 C 將反斜線作為跳脫字元使用。但 C11 的 raw string 可以用來避免此一問題。函式庫 regex 不需要改動到現有的標頭檔，同時也不需要對現有的語言作擴充套件。 通用智慧指標 這些指標是由 TR1 智慧指標演變而來。注意！智慧指標是類別而非一般指標。 shared_ptr 是一引用計數（referencecounted）指標，其行為與一般 C 指標極為相似。在 TR1 的實作中，缺少了一些一般指標所擁有的特色，像是別名或是指標運算。C11 新增前述特色。 一個 shared_ptr 只有在已經沒有任何其它 shared_ptr 指向其原本所指向物件時，才會銷毀該物件。 一個 weak_ptr 指向的是一個被 shared_ptr 所指向的物件。該 weak_ptr 可以用來決定該物件是否已被銷毀。weak_ptr 不能被解參考；想要存取其內部所儲存的指標，只能透過 shared_ptr。有兩種方法可達成此目的。第一，類別 shared_ptr 有一個以 weak_ptr 為引數的建構子。第二，類別 weak_ptr 有一個名為 lock 的成員函式，其返回值為一個 shared_ptr。weak_ptr 並不擁有它所指向的物件，因此不影響該物件的銷毀與否。 底下是一個 shared_ptr 的使用範例： int main stdshared_ptrdouble p_first new double stdshared_ptrdouble p_copy p_first p_copy 212 此時 p_copy 會被銷毀，但動態分配的 double 不會被銷毀。 return 0 此時 p_first 會被銷毀，動態分配的 double 也會被銷毀（因為不再有指標指向它）。 auto_ptr 將會被 C 標準所廢棄，取而代之的是 unique_ptr。unique_ptr 提供 auto_ptr 大部份特性，唯一的例外是 auto_ptr 的不安全、隱性的左值搬移。不像 auto_ptr，unique_ptr 可以存放在 C11 提出的那些能察覺搬移動作的容器之中。 可擴充套件的隨機數功能 C 標準庫允許使用 rand 函式來生成偽隨機數。不過其演演算法則取決於各程式庫開發者。C 直接從 C 繼承了這部份，但是 C11 將會提供產生偽亂數的新方法。 C11 的隨機數功能分為兩部分：第一，一個亂數生成引擎，其中包含該生成引擎的狀態，用來產生亂數。第二，一個分佈，這可以用來決定產生亂數的範圍，也可以決定以何種分佈方式產生亂數。亂數生成物件即是由亂數生成引擎和分佈所構成。 不同於 C 標準庫的 rand 針對產生亂數的機制，C11 將會提供三種演演算法，每一種演演算法都有其強項和弱項： 樣板類 整數 浮點數 品質 速度 狀態數 linear_congruential 整數 低 中等 1 subtract_with_carry 兩者皆可 中等 快 25 mersenne_twister 整數 佳 快 624 C11 將會提供一些標準分佈：uniform_int_distribution（離散型均勻分佈），bernoulli_distribution 伯努利分佈），geometric_distribution（幾何分佈），poisson_distribution（卜瓦松分佈），binomial_distribution（二項分佈），uniform_real_distribution（離散型均勻分佈，exponential_distribution（指數分佈），normal_distribution（常態分佈）和 gamma_distribution（伽瑪分佈）。 底下描述一個亂數生成物件如何由亂數生成引擎和分佈構成： stduniform_int_distributionint distribution 0 99 以離散型均勻分佈方式產生 int 亂數，範圍落在 0 到 99 之間 stdmt19937 engine 建立亂數生成引擎 auto generator stdbind distribution engine 利用 bind 將亂數生成引擎和分佈組合成一個亂數生成物件 int random generator 產生亂數 包裝引用 我們可以透過實體化樣板類 reference_wrapper 得到一個包裝引用（wrapper reference）。包裝引用類似於一般的引用。對於任意物件，我們可以透過模板類 ref 得到一個包裝引用（至於 constant reference 則可透過 cref 得到）。 當樣板函式需要形參的引用而非其複製，這時包裝引用就能派上用場： 此函式將得到形參 r 的引用並對 r 加一 void f int r r 樣板函式 templateclass F class P void g F f P t f t int main int i 0 g f i 實體化 gvoid int r int i 不會被修改 stdcout i stdendl 輸出 0 g f stdref i 實體化 gvoid int rreference_wrapperint i 會被修改 stdcout i stdendl 輸出 1 這項功能將加入標頭檔 functional 之中，而非透過擴充套件語言來得到這項功能。 多型函式物件包裝器 針對函式物件的多型包裝器（又稱多型函式物件包裝器）在語義和語法上和函式指標相似，但不像函式指標那麼狹隘。只要能被呼叫，且其引數能與包裝器相容的都能以多型函式物件包裝器稱之（函式指標，成員函式指標或仿函式）。 透過以下例子，我們可以瞭解多型函式物件包裝器的特性： stdfunctionint int int func 利用樣板類 function 建立包裝器 stdplusint add plus 被宣告為 templateclass T T plus T T 因此 add 的型別是 int add int x int y func add 可行。add 的型參和回返值型別與 func 相符 int a func 1 2 注意：若包裝器 func 沒有參考到任何函式 會丟出stdbad_function_call 例外 stdfunctionbool short short func2 if func2 因為尚未賦值與 func2 任何函式，此條件式為真 bool adjacent long x long y func2 adjacent 可行。adjacent 的型參和回返值型別可透過型別轉換進而與 func2 相符 struct Test bool operator short x short y Test car func stdref car 樣板類stdref 回傳一個 struct car 其成員函式 operator 的包裝 func func2 可行。func2 的型參和回返值型別可透過型別轉換進而與 func 相符 模板類 function 將定義在標頭檔 functional，而不須更動到語言本身。 用於超程式設計的型別屬性 對於那些能自行建立或修改本身或其它程式的程式，我們稱之為超程式設計。這種行為可以發生在編譯或執行期。C 標準委員會已經決定引進一組由模板實現的函式庫，程式員可利用此一函式庫於編譯期進行超程式設計。 底下是一個以超程式設計來計算指數的例子： templateint B int N struct Pow recursive call and recombination enum value BPowB N1value templateint B struct PowB 0 N 0 condition of termination enum value 1 int quartic_of_three Pow3 4value 許多演演算法能作用在不同的資料型別；C 模板支援泛型，這使得程式碼能更緊湊和有用。然而，演演算法經常會需要目前作用的資料型別的資訊。這種資訊可以透過型別屬性（type traits）於模板實體化時將該資訊萃取出來。 型別屬效能識別一個物件的種類和有關一個型別（class 或 struct）的特徵。標頭檔 type_traits 描述了我們能識別那些特徵。 底下的例子說明瞭模板函式elaborate是如何根據給定的資料型別，從而實體化某一特定的演演算法（algorithmdo_it）。 演演算法一 templatebool B struct Algorithm templateclass T1 class T2 static int do_it T1 T2 演演算法二 template struct Algorithmtrue templateclass T1 class T2 static int do_it T1 T2 根據給定的型別，實體化之後的 elaborate 會選擇演演算法一或二 templateclass T1 class T2 int elaborate T1 A T2 B 若 T1 為 int 且 T2 為 float，選用演演算法二 其它情況選用演演算法一 return Algorithmstdis_integralT1value stdis_floating_pointT2valuedo_it A B 此種程式設計技巧能寫出優美、簡潔的程式碼；然而除錯是此種程式設計技巧的弱處：編譯期的錯誤訊息讓人不知所云，執行期的除錯更是困難。 用於計算函式物件返回型別的統一方法 要在編譯期決定一個樣板仿函式的回返值型別並不容易，特別是當回返值依賴於函式的引數時。舉例來說： struct Clear int operator int 引數與回返值的型別相同 double operator double 引數與回返值的型別相同 template class Obj class Calculus public templateclass Arg Arg operator Arg a const return member a private Obj member 實體化樣板類 CalculusClear，Calculus 的仿函式其回返值總是和 Clear 的仿函式其回返值具有相同的型別。然而，若給定類別 Confused struct Confused double operator int 引數與回返值的型別不相同 int operator double 引數與回返值的型別不相同 企圖實體化樣板類 CalculusConfused 將導致 Calculus 的仿函式其回返值和類別 Confused 的仿函式其回返值有不同的型別。對於 int 和 double 之間的轉換，編譯器將給出警告。 模板 stdresult_of 被 TR1 引進且被 C11 所採納，可允許我們決定和使用一個仿函式其回返值的型別。底下，CalculusVer2 物件使用 stdresult_of 物件來推導其仿函式的回返值型別： templateclass Obj class CalculusVer2 public templateclass Arg typename stdresult_ofObj Argtype operator Arg a const return member a private Obj member 如此一來，在實體化 CalculusVer2Confused 其仿函式時，不會有型別轉換，警告或是錯誤發生。 模板 stdresult_of 在 TR1 和 C11 有一點不同。TR1 的版本允許實作在特殊情況下，可以無法決定一個函式呼叫其回返值型別。然而，因為 C11 支援了 decltype，實作被要求在所有情況下，皆能計算出回返值型別。 iota 函式 iota 函式可將給定區間的值設定為從某值開始的連續值，例如將連續十個整數設定為從 1 開始的連續整數（即 1、2、3、4、5、6、7、8、9、10）。 include iostream include array include numeric stdarrayint 10 ai stdiota aibegin aiend 1 for int i ai stdcout 已被移除或是不包含在 C11 標準的特性 預計由 Technical Report 提供支援： 模組 十進位制型別 數學專用函式 延後討論： Concepts（概念 C） 更完整或必備的垃圾回收支援 Reflection Macro Scopes 被移除或廢棄的特性 循序點（sequence point），這個術語正被更為易懂的描述所取代。一個運算可以發生（is sequenced before）在另一個運算之前；又或者兩個運算彼此之間沒有順序關係（are unsequenced）。 export exception specifications 被 stdunique_ptr 取代。 仿函式基底類別 stdunary_function stdbinary_function、函式指標介面卡、類別成員指標介面卡以及繫結器 binder。 編譯器實現 C 編譯器對 C11 新特性的支援情況： Visual C 2010：C0x Core Language Features In VC10 The Table Visual C 2010 與 Visual C 2012 支援的 C11 特性的對比列表：C11 Features Modern C Visual C 2013 支援的 C11 特性的對比列表：C11 Features Modern C Visual C 2015 預覽版支援的 C111417 特性的對比列表：VC2015 Preview 語言特性列表 GCC 481 已實現 C11 標準的所有主要語言特性：Status of Experimental C11 Support in GCC 48 關聯專案 C Technical Report 1 C11 C17 Constexpr，用於編譯時的常量與常量函式。 參考資料 C 標準委員會檔案 Doc No 1401 Jan Kristoffersen（2002 年 10 月 21 日）Atomic operations with multithreaded environments Doc No 1402 Doug Gregor（2002 年 10 月 22 日）A Proposal to add a Polymorphic Function Object Wrapper to the Standard Library Doc No 1403 Doug Gregor（2002 年 11 月 8 日）Proposal for adding tuple types into the standard library Doc No 1424 John Maddock（2003 年 3 月 3 日）A Proposal to add Type Traits to the Standard Library Doc No 1429 John Maddock（2003 年 3 月 3 日）A Proposal to add Regular Expression to the Standard Library Doc No 1449 B Stroustrup G Dos Reis Mat Marcus Walter E Brown Herb Sutter（2003 年 4 月 7 日）Proposal to add template aliases to C Doc No 1450 P Dimov B Dawes G Colvin（2003 年 3 月 27 日）A Proposal to Add General Purpose Smart Pointers to the Library Technical Report Revision 1 Doc No 1452 Jens Maurer April 10 2003 A Proposal to Add an Extensible Random Number Facility to the Standard Library Revision 2 Doc No 1453 D Gregor P Dimov April 9 2003 A proposal to add a reference wrapper to the standard library revision 1 Doc No 1454 Douglas Gregor P Dimov April 9 2003 A uniform method for computing function object return types revision 1 Doc No 1456 Matthew Austern April 9 2003 A Proposal to Add Hash Tables to the Standard Library revision 4 Doc No 1471 Daveed Vandevoorde April 18 2003 Reflective Metaprogramming in C Doc No 1676 Bronek Kozicki September 9 2004 Nonmember overloaded copy assignment operator Doc No 1704 Douglas Gregor Jaakko Järvi Gary Powell September 10 2004 Variadic Templates Exploring the Design Space Doc No 1705 J Järvi B Stroustrup D Gregor J Siek G Dos Reis September 12 2004 Decltype and auto Doc No 1717 Francis Glassborow Lois Goldthwaite November 5 2004 explicit class and default definitions Doc No 1719 Herb Sutter David E Miller October 21 2004 Strongly Typed Enums revision 1 Doc No 1720 R Klarer J Maddock B Dawes H Hinnant October 20 2004 Proposal to Add Static Assertions to the Core Language Revision 3 Doc No 1757 Daveed Vandevoorde January 14 2005 Right Angle Brackets Revision 2 Doc No 1811 J Stephen Adamczyk April 29 2005 Adding the long long type to C Revision 3 Doc No 1815 Lawrence Crowl May 2 2005 ISO C Strategic Plan for Multithreading Doc No 1827 Chris Uzdavinis Alisdair Meredith August 29 2005 An Explicit Override Syntax for C Doc No 1834 Detlef Vollmann June 24 2005 A Pleading for Reasonable Parallel Processing Support in C Doc No 1836 ISOIEC DTR 19768 June 24 2005 Draft Technical Report on C Library Extensions Doc No 1886 Gabriel Dos Reis Bjarne Stroustrup October 20 2005 Specifying C concepts Doc No 1891 Walter E Brown October 18 2005 Progress toward Opaque Typedefs for C0X Doc No 1898 Michel Michaud Michael Wong October 6 2004 Forwarding and inherited constructors Doc No 1919 Bjarne Stroustrup Gabriel Dos Reis December 11 2005 Initializer lists Doc No 1968 V Samko J Willcock J Järvi D Gregor A Lumsdaine February 26 2006 Lambda expressions and closures for C Doc No 1986 Herb Sutter Francis Glassborow April 6 2006 Delegating Constructors revision 3 Doc No 2016 Hans Boehm Nick Maclaren April 21 2002 Should volatile Acquire Atomicity and Thread Visibility Semantics Doc No 2142 ISOIEC DTR 19768 January 12 2007 State of C Evolution between Portland and Oxford 2007 Meetings Doc No 2228 ISOIEC DTR 19768 May 3 2007 State of C Evolution Oxford 2007 Meetings Doc No 2258 G Dos Reis and B Stroustrup Templates Aliases Doc No 2280 Lawrence Crowl May 2 2007 ThreadLocal Storage Doc No 2291 ISOIEC DTR 19768 June 25 2007 State of C Evolution Toronto 2007 Meetings Doc No 2336 ISOIEC DTR 19768 July 29 2007 State of C Evolution Toronto 2007 Meetings Doc No 2389 ISOIEC DTR 19768 August 7 2007 State of C Evolution preKona 2007 Meetings Doc No 2431 SC22WG21N2431 J16070301 October 2 2007 A name for the null pointer nullptr Doc No 2432 ISOIEC DTR 19768 October 23 2007 State of C Evolution postKona 2007 Meeting Doc No 2437 Lois Goldthwaite October 5 2007 Explicit Conversion Operators Doc No 2461 ISOIEC DTR 19768 October 22 2007 Working Draft Standard for programming Language C Doc No 2507 ISOIEC DTR 19768 February 4 2008 State of C Evolution preBellevue 2008 Meeting Doc No 2544 Alan Talbot Lois Goldthwaite Lawrence Crowl Jens Maurer February 29 2008 Unrestricted unions Doc No 2565 ISOIEC DTR 19768 March 7 2008 State of C Evolution postBellevue 2008 Meeting Doc No 2597 ISOIEC DTR 19768 April 29 2008 State of C Evolution preAntipolis 2008 Meeting Doc No 2606 ISOIEC DTR 19768 May 19 2008 Working Draft Standard for Programming Language C Doc No 2697 ISOIEC DTR 19768 June 15 2008 Minutes of WG21 Meeting June 815 2008 Doc No 2798 ISOIEC DTR 19768 October 4 2008 Working Draft Standard for Programming Language C Doc No 2857 ISOIEC DTR 19768 March 23 2009 Working Draft Standard for Programming Language C Doc No 2869 ISOIEC DTR 19768 April 28 2009 State of C Evolution postSan Francisco 2008 Meeting Doc No 3000 ISOISC DTR 19769 November 9 2009 Working Draft Standard for Programming Language C Doc No 3014 Stephen D Clamage November 4 2009 AGENDA PL2216 Meeting No 53 WG21 Meeting No 48 March 813 2010 Pittsburgh PA Doc No 3082 Herb Sutter（2010 年 3 月 13 日）C0x Meeting Schedule Doc No 3092 ISOISC DTR 19769（2010 年 3 月 26 日）Working Draft Standard for Programming Language C Doc No 3126 ISOISC DTR 19769（2010 年 8 月 21 日）Working Draft Standard for Programming Language C Doc No 3225 ISOISC DTR 19769（2010 年 11 月 27 日）Working Draft Standard for Programming Language C Doc No 3242 ISOISC DTR 19769（2011 年 2 月 28 日）Working Draft Standard for Programming Language C Doc No 3290 ISOISC DTR 19769（2011 年 4 月 11 日）Working Draft Standard for Programming Language C 文章 The C Source Bjarne Stroustrup（2006 年 1 月 2 日）A Brief Look at C0x CC Users Journal Bjarne Stroustrup May 2005 The Design of C0x Reinforcing Cs proven strengths while moving into the future Web Log di Raffaele Rialdi（2005 年 9 月 16 日）Il futuro di C raccontato da Herb Sutter Informitcom（2006 年 8 月 5 日）The Explicit Conversion Operators Proposal Informitcom（2006 年 7 月 25 日）Introducing the Lambda Library Dr Dobbs Portal Pete Becker（2006 年 4 月 11 日）Regular Expressions TR1s regex implementation Informitcom（2006 年 7 月 25 日）The Type Traits Library Dr Dobbs Portal Pete Becker（2005 年 5 月 11 日）C Function Objects in TR1 The C Source Howard E Hinnant Bjarne Stroustrup and Bronek Kozicki（2008 年 3 月 10 日）A Brief Introduction to Rvalue References DevXcom Special Report（2008 年 8 月 18 日）C0x The Dawning of a New Standard 外部連結 The C Standards Committee Bjarne Stroustrups homepage C0X The New Face of Standard C Herb Sutters blog coverage of C0X A talk on C0x given by Bjarne Stroustrup at the University of Waterloo A quick and dirty introduction to C0x as of November 2007 The State of the Language An Interview with Bjarne Stroustrup August 15 2008 Working draft for the C language October 4 2008 CategoryC Category 程式語言標準