若要了解有關 Visual Studio 2017 RC 的最新文檔,請參閱 Visual Studio 2017 RC 文檔。html
本文描述了 Visual C++ 中的 C++11/14/17 功能。程序員
本文內容express
C++ 14 核心語言功能less
功能表指南ide
C++11 功能列表
Visual C++ 實現了 C++11 核心語言規範 中的絕大多數功能、許多 C++14 庫功能和某些爲 C++17 建議的功能。 下表列出了 C++11/14/17 核心語言功能及其在 Visual Studio 20十、Visual Studio 2012 中的 Visual C++、Visual Studio 2013 中的 Visual C++ 和 Visual Studio 2015 中 Visual C++ 中的實現狀態。
C++11 核心語言功能 | Visual Studio 2010 | Visual Studio 2012 | Visual Studio 2013 | Visual Studio 2015 |
---|---|---|---|---|
右值引用 v0.1、v1.0、v2.0、v2.1、v3.0 | 2.0 版 | 2.1* 版 | 2.1* 版 | v3.0 |
引用限定符 | 否 | 否 | 否 | 是 |
非靜態數據成員初始值設定項 | 否 | 否 | 是 | 是 |
可變參數模板 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 | 是 | 是 | 是 | 是 |
強類型的枚舉 | 部分 | 是 | 是 | 是 |
前向聲明枚舉 | 否 | 是 | 是 | 是 |
特性 | 否 | 否 | 否 | 是 |
constexpr | 否 | 否 | 否 | 是 |
對齊方式 | TR1 | 部分 | 部分 | 是 |
委託構造函數 | 否 | 否 | 是 | 是 |
繼承構造函數 | 否 | 否 | 否 | 是 |
顯式轉換運算符 | 否 | 否 | 是 | 是 |
char16_t/char32_t | 否 | 否 | 否 | 是 |
Unicode 字符串文本 | 否 | 否 | 否 | 是 |
原始字符串文本 | 否 | 否 | 是 | 是 |
文本中的通用字符名 | 否 | 否 | 否 | 是 |
用戶定義的文本 | 否 | 否 | 否 | 是 |
標準佈局和普通類型 | 否 | 是 | 是 | 是 |
默認函數和已刪除的函數 | 否 | 否 | 是* | 是 |
擴展的友元聲明 | 是 | 是 | 是 | 是 |
擴展的 sizeof | 否 | 否 | 否 | 是 |
內聯命名空間 | 否 | 否 | 否 | 是 |
無限制的聯合 | 否 | 否 | 否 | 是 |
做爲模板參數的本地和未命名類型 | 是 | 是 | 是 | 是 |
基於範圍的 for 循環 | 否 | 是 | 是 | 是 |
override 和 final v0.8、v0.9、v1.0 | 部分 | 是 | 是 | 是 |
最低 GC 支持 | 是 | 是 | 是 | 是 |
noexcept | 否 | 否 | 否 | 是 |
[本文內容]
C++11 核心語言功能:併發 | Visual Studio 2010 | Visual Studio 2012 | Visual Studio 2013 | Visual Studio 2015 |
---|---|---|---|---|
改寫的序列點 | 不可用 | 不可用 | 不可用 | 是 |
原子 | 否 | 是 | 是 | 是 |
強比較和交換 | 否 | 是 | 是 | 是 |
雙向界定 | 否 | 是 | 是 | 是 |
內存模型 | 不可用 | 不可用 | 不可用 | 是 |
數據依賴項排序 | 否 | 是 | 是 | 是 |
數據依賴項排序:函數批註 | 否 | 否 | 否 | 是 |
exception_ptr | 是 | 是 | 是 | 是 |
quick_exit | 否 | 否 | 否 | 是 |
信號處理程序中的原子化 | 否 | 否 | 否 | 否 |
線程本地存儲區 | 部分 | 部分 | 部分 | 是 |
神奇的靜態對象 | 否 | 否 | 否 | 是 |
[本文內容]
C++11 核心語言功能:C99 | Visual Studio 2010 | Visual Studio 2012 | Visual Studio 2013 | Visual Studio 2015 |
---|---|---|---|---|
__func__ | 部分 | 部分 | 部分 | 是 |
C99 預處理器 | 部分 | 部分 | 部分 | 部分 |
long long | 是 | 是 | 是 | 是 |
擴展的整型 | 不可用 | 不可用 | 不可用 | 不可用 |
[本文內容]
功能 | Visual Studio 2013 | Visual Studio 2015 |
上下文轉換的已調整 workding | 是 | 是 |
二進制文本 | 否 | 是 |
auto 和 decltype(auto) 返回類型 | 否 | 是 |
init-capture | 否 | 是 |
泛型 lambda | 否 | 是 |
變量模板 | 否 | 否 |
擴展的 constexpr | 否 | 否 |
聚合的 NSDMI | 否 | 否 |
避免/合成分配 | 否 | 否 |
[已棄用] 特性 | 否 | 否 |
大小通過調整的分配 | 否 | 是 |
數字分隔符 | 否 | 是 |
功能 | Visual Studio 2013 | Visual Studio 2015 |
針對自動使用大括號內的初始值設定項列表的新建規則 | 否 | 否 |
簡要靜態斷言 | 否 | 否 |
模板-參數模板的類型名稱 | 否 | 否 |
刪除三字符組 | 是 | 是 |
嵌套的命名空間定義 | 否 | 否 |
N4259 std::uncaught_exceptions() | 否 | 否 |
N4261 修復限定轉換 | 否 | 否 |
N4266 命名空間和枚舉器的特性 | 否 | 否 |
N4267 u8 字符文本 | 否 | 否 |
N4268 容許更多非類型模板參數 | 否 | 否 |
N4295 Fold 摺疊表達式 | 否 | 否 |
等待/繼續 | 否 | 是 |
功能表指南
說明 |
---|
如下描述中的版本標識符(v0.一、v1.0、v2.0、v2.一、v3.0)僅用來演示 C++11 的發展。 標準自己不會使用它們。 |
N1610「經過右值澄清類對象的初始化」是早期在不引用右值的狀況下支持移動語義的一種嘗試。 爲方便討論,咱們稱之爲「右值引用 0.1 版」。 它由「右值引用 v1.0」取代。 「右值引用 v2.0」是 Visual Studio 2010 中的 Visual C++ 功能的基礎,它禁止將右值引用綁定到左值,所以能夠解決主要的安全性問題。 「右值引用 v2.1」從新定義了此規則。 讓咱們看一下 vector<string>::push_back()
,它具備重載 push_back(const string&)
和 push_back(string&&)
以及調用 v.push_back("strval")
。 表達式 "strval"
是字符串,而且是左值。 (其餘文本爲右值,如整數 1729,但字符串有些特殊,由於它們是數組。) 「右值引用 2.0 版」規則顯示,string&&
沒法綁定到 "strval"
,由於 "strval"
是左值,所以 push_back(const string&)
是惟一可行的重載。 這將建立一個臨時 std::string
,並將它複製到向量中,而後銷燬效率不過高的臨時 std::string
。 「右值引用 2.1 版」規則確認,將 string&&
綁定到 "strval"
將建立臨時 std::string
,而且該臨時字符串爲右值。 所以,push_back(const string&)
和 push_back(string&&)
都是可行的,但首選 push_back(string&&)
。 將構造一個臨時 std::string
,而後將它移至向量中。 這樣效率更高。
「右值引用 v3.0」將添加新規則,以在特定條件下自動生成移動構造函數和移動賦值運算符。 這是在 Visual Studio 2015 中實現的。
[本文內容]
在 lambda 函數選入到工做文件(「0.9」版)而且已添加可變的 lambda(「1.0」版)以後,標準化委員會全面修訂了措詞。 這產生了 lambda「1.1」版,這個版本如今已徹底受支持。 lambda 1.1 版的措詞闡明瞭在特殊案例(例如引用靜態成員或嵌套 lambda)中會發生的狀況。 這將修復由複雜 lambda 觸發的問題。 此外,無狀態的 lambda 如今可轉換爲函數指針。 這沒有包含在 N2927 措詞中,可是不管如何都會將它計做 lambda 1.1 版的一部分。C++11 5.1.2 [expr.prim.lambda]/6 具備如下說明:「無 lambda-capture
的 lambda-expression
的閉包類型使用一個公共的非虛擬、非顯式常量轉換函數指向一個具備與閉包類型的函數調用運算符相同的參數和返回類型的函數。 此轉換函數返回的值應爲一個函數的地址,調用該函數時,其效果和調用閉包類型的函數調用運算符相同。」 (Visual Studio 2012 中的 Visual C++ 實現的效果甚至更好,由於它使無狀態的 lambda 可轉換爲具備任意調用約定的函數指針。 當你在使用期待像 __stdcall
函數指針這類對象的 API 時,這點很重要。)
[本文內容]
在 decltype 選入到工做文件(1.0 版)後,在最後時刻收到了一個小的但很重要的修復(1.1 版)。 這對從事 STL 和 Boost 工做的程序員頗有好處。
[本文內容]
Visual Studio 2010 中的 Visual C++ 部分支持 強類型的枚舉(具體而言,支持有關顯式指定的基礎類型部分)。 如今這些在 Visual Studio 中已徹底實現,前向聲明枚舉的 C++11 語義也已徹底實現。
[本文內容]
選入工做文件的對齊方式提案中的核心語言關鍵字 alignas
/alignof
在 Visual Studio 2015 中已實現。 Visual Studio 2010 中的 Visual C++ 具備來自 TR1 的 aligned_storage
。Visual Studio 2012 中的 Visual C++ 已將 aligned_union
和 std::align()
添加到標準庫,並且重大的問題已在 Visual Studio 2013 中的 Visual C++ 中修復。
[本文內容]
來自 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
類型)。 這將遵循建議的解決方法,但其將中斷依賴於先前行爲的全部代碼。
若是須要標識類型特徵,請不要使用 std::identity
中定義的非標準 <type_traits>
,由於它對 <void>
無效。 相反,實現你本身的標識類型特徵以知足你的需求。 如下是一個示例:
C++
template <typename T> struct Identity { typedef T type; };
說明 |
---|
有關其餘重大更改,請參閱Visual C++ 2015 中的重大更改。 |
[本文內容]
這些函數如今均受支持,但此種狀況例外:對於默認函數,不支持使用 =default
請求識別成員的移動構造函數和移動賦值運算符。 複製和移動操做並不按照標準規定的方式進行精確交互 - 例如,指定刪除移動會同時禁止顯示覆制操做,但 Visual Studio 2013 中的 Visual C++ 不會。
有關如何使用默認函數和已刪除的函數的信息,請參閱函數。
[本文內容]
這經歷了短暫而複雜的發展。 最初,在 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 說明符。
[本文內容]
原子化、強比較和交換、雙向界定和數據依賴項排序指定如今已實現的標準庫機制。
相關 STL 標頭: <atomic>、<chrono>、<condition_variable>、<future>、<mutex>、<ratio>、<scoped_allocator> 和 <thread>。
[本文內容]
C++11 核心語言功能:C99 表列出了兩個項的「部分」實現。 對於預約義標識符 __func__
,列出「分部」,由於對非標準擴展 __FUNCDNAME__
、__FUNCSIG__
和 __FUNCTION__
提供了支持。 有關詳細信息,請參閱 預約義的宏。 對於 C99 預處理器規則,列出「分部」,由於支持可變參數宏。 有關詳細信息,請參閱 Variadic 宏。
[本文內容]
這涵蓋核心語言。 至於 C++11 標準庫,咱們雖沒有漂亮的功能比較表,但 Visual Studio 2012 中的 Visual C++ 已實現此功能,但具備兩個例外。 首先,當某個庫功能依賴於編譯器中缺乏的功能時,該功能要麼是模擬的(例如,make_shared<T>()
的模擬可變參數模板),要麼沒有實現。 (僅有少數狀況如今已經在 Visual Studio 2013 中的 Visual C++ 中徹底實現,其中最值得注意的是 <initializer_list>
。) 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()
已在全部包含「任意」數量參數的容器中實現(請參見「模擬的可變參數」部分)。 例如,vector<T>
具備「template <typename... Args> void emplace_back(Args&&... args)
」(它在向量的後面從任意數量的任意參數時直接構造元素類型 T,這稱爲「徹底轉發」)。 這相對於 push_back(T&&)
(將涉及額外的移動構造和析構)效率更高。
可變參數: Visual Studio 2012 中的 Visual C++ 具備用於模擬可變參數模板的方案。 在 Visual Studio 2013 中的 Visual C++ 中,取消了模擬,並徹底實現了可變參數。 若是你的代碼依賴舊的模擬可變參數行爲,則必須修復它。 可是,切換到實際可變參數模板增長了編譯次數,並下降了編譯器的內存消耗。
顯式轉換運算符:在覈心語言中,顯式轉換運算符是一項常規功能 — 例如,你能夠具備 explicit operator MyClass()
。 可是,標準庫當前僅使用一種形式:explicit operator bool()
,這使類成爲安全的布爾值可測試的類。 (無格式「operator bool()
」是很是危險的。) 過去,Visual C++ 模擬了帶有 explicit operator bool()
的 operator pointer-to-member()
,這致使各類問題,而且效率有些低下。 如今,徹底移除了此「虛擬 bool」工做區。
隨機性: uniform_int_distribution
如今是徹底公平的,而且在 <algorithm>
中實現了 shuffle()
,這樣即可以直接接受統一隨機數生成器,如 mersenne_twister
。
防止重載 address-of 運算符:C++98/03 禁止 STL 容器的元素重載其 address-of 運算符。 這是相似 CComPtr
的類完成的操做,所以使 STL 避免此類重載須要相似 CAdapt
的幫助程序類。 開發 Visual Studio 2010 中的 Visual C++ 時,STL 更改使其在更多狀況下拒絕重載 address-of 運算符。 C++11 更改了相關要求,使得重載 address-of 運算符可接受。 Visual Studio 2010 中的 C++11 和 Visual C++ 提供幫助程序函數 std::addressof()
,此函數可獲取對象的真實地址(不管運算符是否重載)。 在發佈 Visual Studio 2010 中的 Visual C++ 以前,咱們已嘗試將「&elem
」的匹配項替換爲具備必定抵抗性的「std::addressof(elem)
」。Visual Studio 2012 中的 Visual C++ 更進一步,這樣重載 address-of 運算符的類就能在整個 STL 中使用了。
Visual Studio 2012 中的 Visual C++ 在下列方面超出了 C++11 的範圍:
SCARY 迭代器:實現了 SCARY 迭代器,如 N2911「在泛型類中最小化依賴項以得到更快且更小的程序」和 N2980「SCARY 迭代器分配和安裝,初版」中所述,這在 C++11 標準是容許的,但不是必需的。
文件系統:已添加 TR2 建議中的 <filesystem>
標頭。 它提供 recursive_directory_iterator
和其餘有趣功能。 在 TR2 的工做凍結以前,因爲 C++0x 很晚才投入運行且將更改成 C++11,所以從 Boost.Filesystem V2 派生出了 2006 協議。 它稍後改進爲 Boost.Filesystem V3,這在 Visual Studio 2015 中實現。
一個主要優化! 如今,咱們的全部容器相對於當前的表示形式都具備最小的合適大小。 這指的是容器對象自己,而不是它們指向的內容。 例如,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++ 14 庫功能:
「透明運算符函子」less<>
、greater<>
、plus<>
、multiplies<>
等。
make_unique<T>(args...)
和 make_unique<T[]>(n)
cbegin()
/cend()
、rbegin()
/rend()
和 crbegin()
/crend()
非成員函數。