共用方式為


C++11 功能的支援 (現代 C++)

本文章描述 Visual C++ 中的 C++11 功能。

本文內容

  • C++11 Feature List

    • Core Language Feature Table

    • Core Language Feature Table: Concurrency

    • Core Language Feature Table: C99

  • Guide To Feature Tables

    • Rvalue References

    • Lambdas

    • decltype

    • Strongly Typed/Forward Declared enums

    • Alignment

    • Standard-Layout and Trivial Types

    • Defaulted and deleted functions

    • override and final

    • Atomics, and more

    • C99 __func__ and preprocessor rules

  • Standard Library features

C++11 功能清單

Visual Studio 2010 中的 Visual C++ 實作了 C++11 核心語言規格 (英文) 中的許多功能,而 Visual Studio 2012 中的 Visual C++ 加入了更多 C++11 功能。 Visual Studio 2013 中的 Visual C++ 將此涵蓋範圍進一步延伸,也可支援一些 C++14 程式庫功能。 下表列出在 Visual Studio 2010、Visual Studio 2012 中的 Visual C++ 和 Visual Studio 2013 中的 Visual C++ 的 Visual C++ 中,C++11 核心語言功能及其實作情形。

C++11 核心語言功能表

C++11 核心語言功能 (英文)

Visual Studio 2010

Visual Studio 2012

Visual Studio 2013

右值參考 v0.1 (英文)、v1.0 (英文) v2.0 (英文) v2.1 (英文) v3.0 (英文)

v2.0

v2.1*

v2.1*

ref 限定詞 (英文)

非靜態資料成員初始設定式 (英文)

Variadic 範本v0.9 (英文)、v1.0 (英文)

初始設定式清單 (英文)

static_assert (英文)

auto v0.9 (英文)、v1.0 (英文)

v1.0

v1.0

v1.0

尾端傳回類型 (英文)

Lambdas v0.9 (英文)、v1.0 (英文)、v1.1 (英文)

v1.0

v1.1

v1.1

decltype v1.0 (英文)、v1.1 (英文)

v1.0

v1.1**

v1.1

右角括弧 (英文)

函式範本的預設範本引數 (英文)

運算式 SFINAE (英文)

別名範本 (英文)

Extern 範本 (英文)

nullptr (英文)

強類型列舉 (英文)

Partial

向前宣告列舉 (英文)

屬性 (英文)

constexpr (英文)

對其 (英文)

TR1

Partial

Partial

委派建構函式 (英文)

繼承建構函式 (英文)

明確轉換運算子 (英文)

char16_t/char32_t (英文)

Unicode 字串常值 (英文)

原始字串常值 (英文)

長值中的通用字元名稱 (英文)

使用者定義常值 (英文)

標準配置和 Trivial 類型 (英文)

預設和已刪除的函式 (英文)

是*

擴充 friend 宣告 (英文)

擴充 sizeof (英文)

內嵌命名空間 (英文)

無限制的等位 (英文)

當做範本引數的區域和未命名類型 (英文)

範圍架構的 for 迴圈 (英文)

override 和 final v0.8 (英文)、v0.9 (英文)、v1.0 (英文)

Partial

最低 GC 支援 (英文)

noexcept (英文)

[go to top]

C++11 核心語言功能表:並行

C++11 核心語言功能:並行

Visual Studio 2010

Visual Studio 2012

Visual Studio 2013

改寫的序列點 (英文)

N/A

N/A

N/A

Atomics (英文)

強式比較和交換 (英文)

雙向柵欄 (英文)

記憶體模型 (英文)

N/A

N/A

N/A

資料相依性順序 (英文)

資料相依性順序:函式註釋 (英文)

exception_ptr (英文)

quick_exit (英文)

訊號處理常式中的 Atomics (英文)

執行緒區域儲存區 (英文)

Partial

Partial

Partial

Magic 靜態變數 (英文)

[go to top]

C++11 核心語言功能:C99

C++11 核心語言功能:C99

Visual Studio 2010

Visual Studio 2012

Visual Studio 2013

__func__ (英文)

Partial

Partial

Partial

C99 前置處理器 (英文)

Partial

Partial

Partial

long long (英文)

擴充整數類型 (英文)

N/A

N/A

N/A

[go to top]

功能表指南

右值參考

注意事項注意事項

下列描述中的版本編號 (v0.1、v1.0、v2.0、v2.1、v3.0) 是用來表示 C++11 的發展程度。標準本身不使用這些編號。

N1610「說明透過右值的類別物件初始化」 (英文) 是早期不使用右值參考啟用移動語意的嘗試。 在這個討論中,我們將其稱為「右值參考 v0.1」。 它已被「右值參考 v1.0 (英文)」取代。「右值參考 v2.0 (英文)」是 Visual C++ 在 Visual Studio 2010 中的工作基礎,藉由禁止右值參考繫結至左值的方式,修正主要安全問題。" 右值參考 v2.1 (英文)」會對此規則作進一步修改。 假設 vector<string>::push_back() 中具有 push_back(const string&) 和 push_back(string&&) 多載,以及 v.push_back("strval") 呼叫。 "strval" 運算式是字串常值,而且是左值。 (整數 1729 等其他常值是右值,但字串常值是特殊的,因為它們是陣列)。「右值參考 v2.0」規則規定,string&& 無法繫結到 "strval",因為 "strval" 是左值,因此 push_back(const string&) 是唯一可行的多載。 這會建立暫存 std::string,將其複製到向量,然後終結暫存 std::string,但不是很有效率。 「右值參考 v2.1」規則認為,string&& 繫結至 "strval" 會建立暫存的 std::string,而且暫存的是右值。 因此,push_back(const string&) 和 push_back(string&&) 是可行的,而以 push_back(string&&) 較為慣用。 會建構暫存 std::string,然後將其移至向量。 這會更有效率。

「右值參考 v3.0 (英文)」加入新規則,會在特定情況下自動產生移動建構函式和移動指派運算子。 不過,由於時間和資源條件約束,這在 Visual Studio 2013 中的 Visual C++ 中未實作。

[go to top]

Lambdas

lambda 函式經表決通過納入工作文件 (版本 "0.9" (英文)),並加入可變動 Lambda (版本 "1.0" (英文)) 之後,標準化委員會翻修了用字方式。 這即產生現在已完全支援的 Lambdas 版本 "1.1" (英文)。 Lambda v1.1 的用字方式可釐清在參考靜態成員或巢狀 Lambda 等隱密案例下應該會發生什麼情況。 這會修正由複雜 Lambda 所觸發的問題。 此外,無狀態 Lambda 現在可轉換為函式指標。 這使用的不是 N2927 用語,但還是視為 Lambda v1.1 的一部分。 C++11 (英文) 5.1.2 [expr.prim.lambda]/6 有這樣的描述:「沒有 lambda-capture 之 lambda-expression 的結束類型,具有函式至函式指標的公用、非虛擬、非明確的常數轉換函式,而函式指標的參數和傳回類型與結束類型的函式呼叫運算子相同。 這個轉換函式傳回的值將會是函式的位址,叫用該函式與叫用結束類型的函式呼叫運算子有相同的效果」。(Visual Studio 2012 中的 Visual C++ 實作甚至更好,因為這會讓無狀態 Lambda 得以轉換為有任意呼叫慣例的函式指標。 當您使用需要 __stdcall 函式指標的 API 時,這點很重要)。

[go to top]

decltype

decltype 經表決通過,放入工作文件 (版本 1.0 (英文)) 之後,它在最後時刻獲得小型但重要的修正 (版本 1.1 (英文))。 這對使用 STL 和 Boost 的程式設計人員而言,關係重大。

[go to top]

強類型/向前宣告列舉

Visual Studio 2010 中的 Visual C++ 部分支援強類型列舉 (英文),特別是有關明確指定的基礎類型部分。 目前在 Visual Studio 中已完全實作這些列舉,同時也完全實作向前宣告列舉 (英文) 的 C++11 語意。

[go to top]

對齊方式

不會實作已表決納入工作文件的對齊提議 (英文) 中的核心語言關鍵字 alignas/alignof。 Visual Studio 2010 中的 Visual C++ 具有 TR1 的 aligned_storage。 Visual Studio 2012 中的 Visual C++ 已將 aligned_union 和 std::align() 加入標準程式庫,且重大議題已在 Visual Studio 2013 中的 Visual C++ 中修正。

[go to top]

標準配置和 Trivial 類型

N2342「POD 重新造訪:解決核心問題 568 (修訂 5)」 (英文) 中的建議變更是將 is_trivial 和 is_standard_layout 加入至標準範本庫的 <type_traits>。 (N2342 調整了大量的核心語言文字,不過,編譯器變更不是必要的)。這些類型特性在 Visual Studio 2010 的 Visual C++ 中有提供,但它們只是重複的 is_pod。 因此,文件前面的表格會說「否」表示不支援。 現在這些特徵是由專為提供精確回應而設計的編譯器攔截所支援。

STL 的 common_type<> 會在 Visual Studio 2013 中的 Visual C++中收到必要的修正。 common_type<> 的 C++11 規格會產生未預期和不想要的結果,尤其是使 common_type<int, int>::type 傳回 int&&。 因此,Visual Studio 2013 中的 Visual C++ 會實作程式庫工作小組問題 2141 的建議解決方法 (英文),它會讓 common_type<int, int>::type 傳回 int。

這項變更的副作用就是識別案例不再適用 (common_type<T> 不一定會產生 T 類型)。 這個結果符合建議的解決方法,不過它會破壞依賴之前行為的任何程式碼。

如果您需要識別類型特性,請不要使用 <type_traits> 中定義的非標準 std::identity,因為它不適用 <void>。 請改為依照您的需求,實作自己的識別類型特性。 以下為範例:

template <typename T> struct Identity {
    typedef T type;
};
注意事項注意事項

如需其他重大變更,請參閱 Visual C++ 的重大變更

[go to top]

預設和已刪除的函式

現在可支援這些函式,除了這個例外狀況:對於預設的函式,不支援使用 =default 要求成員移動建構函式和移動指派運算子。 複製和移動無法像標準所規定的那樣精準互動。例如,刪除移動時也會指定要隱藏複製,但 Visual Studio 2013 中的 Visual C++ 則不會如此。

如需關於使用預設和刪除之函式方式的詳細資訊,請參閱 C++ 函式定義

[go to top]

override 和 final

經歷了短暫但複雜的演變。 原先在 0.8 版 (英文) 中,有 [[override]]、[[hiding]] 及 [[base_check]] 屬性。 接著在 0.9 版 (英文) 中,這些屬性已消失,由內容關鍵字取而代之。 最後,在 1.0 版 (英文) 中,它們則降至類別的 "final",以及函式的 "override" 及 "final"。 這使得此版本成為「加強擴充」,因為 Visual Studio 2010 中的 Visual C++ 已經在函式中支援這個 "override" 語法,而且其語意相當接近 C++11 的語意。 也支援 "final ",不過是在其他拼字 "sealed" 之下。 現在可完全支援「override」和「final」的標準拼字及語意。 如需詳細資訊,請參閱override 規範final 規範

[go to top]

Atomics 和其他

Atomics (英文)、強式比較和交換 (英文)、雙向柵欄 (英文) 及資料相依性順序 (英文) 會指定目前已實作的標準程式庫機制。

相關 STL 標頭: <atomic><chrono><condition_variable><future><mutex><ratio><scoped_allocator><thread>

[go to top]

C99 __func__ 及前置處理器規則

表格 Core Language Feature Table: C99 會列出兩個項目的「部分」實作。 對於預先定義的識別項 __func__,會列出「部分」,因為支援會提供給非標準擴充功能 __FUNCDNAME__、__FUNCSIG__ 及 __FUNCTION__。 如需詳細資訊,請參閱預先定義的巨集。 對於 C99 前置處理器規則,會列出「部分」,因為支援 variadic 巨集。 如需詳細資訊,請參閱Variadic 巨集

[go to top]

標準程式庫功能

可涵蓋核心語言。 對於 C++11 標準程式庫,我們沒有正式的功能比較表,但是 Visual Studio 2012 中的 Visual C++ 會加以實作,其中有兩個例外狀況。 首先,當程式庫功能取決於編譯器中遺漏的功能時,表示程式庫功能為模擬 (例如,make_shared<T>() 的模擬 variadic 範本) 或並未實作。 (現在已在 <initializer_list> 完全實作的案例只有少數幾個,尤其是 Visual Studio 2013 中的 Visual C++)。C99 已經在 Visual Studio 2013 中的 Visual C++ 中實作,而且也提供 C++ 包裝函式標頭,其中有極少數的例外狀況。 如需詳細資訊,請參閱 Visual Studio 2013 中的 C99 程式庫支援 (英文)。

Visual Studio 2012 中的 Visual C++ 和 Visual Studio 2013 中的 Visual C++ 中的部分變更清單如下:

**定位:**根據 C++11 規定,在「任意」引數數目的所有容器中實作 emplace()/emplace_front()/emplace_back()/emplace_hint()/emplace_after() (請參閱<Simulated variadics>一節)。 例如,vector<T> 具有 "template <typename... Args> void emplace_back(Args&&... args)",這會直接在向量後面從任意數目的任意引數完全向前建構類型 T 的項目。 這比 push_back(T&&) 更有效率,後者需要額外移動建構和解構。

Variadics:Visual Studio 2012 中的 Visual C++ 有模擬 variadic 範本的配置。 在 Visual Studio 2013 中的 Visual C++ 中,模擬已消失,並完整實作 variadic。 如果程式碼依賴舊版模擬的 variadic 行為,您必須進行修正。 不過,改用實際的 variadic 樣板後已縮短編譯時間並且減少編譯器記憶體使用量

明確轉換運算子:在核心語言中,明確轉換運算子是一般功能,例如,您可以擁有 explicit operator MyClass()。 不過,標準程式庫目前只使用一種形式:explicit operator bool(),此形式可讓類別安全地進行布林值測試。 (簡單的「operator bool()」非常危險)。在過去,Visual C++ 會模擬 explicit operator bool() 和 operator pointer-to-member(),導致各種問題並且使效率些微不足。 現在已完全移除這個「假的 bool」解決方法。

**隨機:**uniform_int_distribution 現在已經完全無偏誤,而且 shuffle() 會在 <algorithm> 中實作,可直接接受統一亂數產生器如 mersenne_twister。

多載傳址運算子抗性: C++98/03 已禁止 STL 容器的項目多載其傳址運算子。 像 CComPtr 這樣的類別所做的就是此類工作,以便要求諸如 CAdapt 的 Helper 類別避免 STL 產生此類多載。 在開發 Visual Studio 2010 中的 Visual C++ 期間,STL 的變更會讓它在更多情況下拒絕多載傳址運算子。 C++11 變更需求以接受已多載的傳址運算子。 C++11 和 Visual Studio 2010 中的 Visual C++ 會提供 Helper 函式 std::addressof(),這可以不考慮運算子多載而取得物件真正的位址。 在發行 Visual Studio 2010 中的 Visual C++ 之前,我們嘗試以 "std::addressof(elem)" 取代"&elem",這樣也會有抵抗性。 Visual Studio 2012 中的 Visual C++ 更進一步之後,多載其傳址運算子的類別就可在整個 STL 中使用。

Visual Studio 2012 中的 Visual C++ 多方面超越了 C++11:

**SCARY 迭代器:**SCARY 迭代器已依照 C++11 標準所允許 (但非必要) 的方式完成實作,如文件 N2911:<最小化泛型類別中的相依性,以產生更快速且更小型的程式> (英文) 和 N2980:<SCARY 迭代器指派和初始化 (修訂 1)> 所述。

**檔案系統:**已加入 TR2 提議 (英文) 的 <filesystem> 標頭。 它提供 recursive_directory_iterator 及其他有趣的功能。 在 TR2 的工作因為 C++0x 延遲且即將變更為 C++11 而凍結之前,2006 提案已自 Boost.Filesystem V2 (英文) 衍生而出。 它之後逐漸發展成 Boost.Filesystem V3,但在 Visual Studio 2012 中的 Visual C++ 中並未進行實作。

而且是主要最佳化! 根據目前的表示,我們所有的容器現在是最佳小型。 這指的是容器物件本身,而非它們所指向的內容。 例如,std::vector 會包含三個原始指標。 在 Visual Studio 2010 中的 Visual C++ 中,x86 發行模式的 std::vector 為 16 位元組。 在 Visual Studio 2012 中的 Visual C++ 中,這是 12 個位元組,也就是最佳的小型。 此事非同小可:如果您的程式中有 100,000 個向量,Visual Studio 2012 中的 Visual C++ 就會為您節省 400,000 個位元組。 降低記憶體使用量可節省空間和時間。

這是藉由避免儲存空的配置器和比較子的方式達到目的,因為 std::allocator 和 std::less 是無狀態的。 (只要是無狀態,自訂配置器/比較子也啟用這些最佳化。 可設定狀態的配置器/比較子存放顯然是無法避免的,但這些情況非常罕見)。

Visual Studio 2013 中的 Visual C++ 進一步超越了 C++11,可實作某些重要的 C++14 文件庫功能:

  • 「透明運算子函式」less<>greater<>plus<>multiplies<>,依此類推。

  • make_unique<T>(args...)make_unique<T[]>(n)

  • cbegin()/cend()rbegin()/rend()crbegin()/crend() 非成員函式。

[go to top]

請參閱

參考

C++ 中的 Lambda 運算式

以範圍為基礎的 for 陳述式 (C++)

概念

Visual Studio 2013 中 Visual C++ 的新功能

Visual C++ 的重大變更

其他資源

歡迎回到 C++ (現代 C++)

C++ 語言參考

C++ 標準程式庫參考

Visual C++ 團隊部落格