|
C++14是C++的現(xiàn)行標(biāo)準(zhǔn)的非正式名稱,正式名稱為"International Standard ISO/IEC 14882:2014(E) Programming Language C++"。C++14旨在作為C++11的一個(gè)小擴(kuò)展,主要提供漏洞修復(fù)和小的改進(jìn)。C++14標(biāo)準(zhǔn)的委員會(huì)草案(Committee Draft)N3690于2013年5月15日發(fā)表。[1]工作草案(Working Draft)N3936已于2014年03月02日完成。最終的投票期結(jié)束于2014年8月15日,結(jié)果(一致通過)已于8月18日公布。[2] 新的語言特性以下為在C++14中被加入語言核心的特性。 泛型的lambda在C++11中,lambda函數(shù)的形式參數(shù)需要被聲明為具體的類型。C++14放寬了這一要求,允許lambda函數(shù)的形式參數(shù)聲明中使用類型說明符 auto lambda = [](auto x, auto y) {return x + y;}
泛型lambda函數(shù)遵循模板參數(shù)推導(dǎo)的規(guī)則。以上代碼的作用與下面的代碼相同:[4] struct unnamed_lambda{
template<typename T, typename U>
auto operator()(T x, U y) const {return x + y;}};auto lambda = unnamed_lambda();
Lambda捕獲部分中使用表達(dá)式C++11的lambda函數(shù)通過值拷貝(by copy)或引用(by reference)捕獲(capture)已在外層作用域聲明的變量。這意味著lambda的值成員不可以是move-only的類型。[5] C++14允許被捕獲的成員用任意的表達(dá)式初始化。這既允許了capture by value-move,也允許了任意聲明lambda的成員,而不需要外層作用域有一個(gè)具有相應(yīng)名字的變量。[6] 這是通過使用一個(gè)初始化表達(dá)式完成的: auto lambda = [value = 1] {return value;}
lambda函數(shù) 使用標(biāo)準(zhǔn)函數(shù) auto ptr = std::make_unique<int>(10); //See below for std::make_uniqueauto lambda = [ptr = std::move(ptr)] {return *ptr;}
聲明 函數(shù)返回類型推導(dǎo)C++11允許lambda函數(shù)根據(jù)return語句的表達(dá)式類型推斷返回類型。C++14為一般的函數(shù)也提供了這個(gè)能力。C++14還拓展了原有的規(guī)則,使得函數(shù)體并不是 為了啟用返回類型推導(dǎo),函數(shù)聲明必須將 auto DeduceReturnType(); //返回類型由編譯器推斷 如果函數(shù)實(shí)現(xiàn)中含有多個(gè)return語句,這些表達(dá)式必須可以推斷為相同的類型。[9] 使用返回類型推導(dǎo)的函數(shù)可以前向聲明,但在定義之前不可以使用。它們的定義在使用它們的翻譯單元(translation unit)之中必須是可用的。 這樣的函數(shù)中可以存在遞歸,但遞歸調(diào)用必須在函數(shù)定義中的至少一個(gè)return語句之后:[9] auto Correct(int i) {
if (i == 1)
return i; // 返回類型被推斷為int
else
return Correct(i-1)+i; // 正確,可以調(diào)用}auto Wrong(int i){
if(i != 1)
return Wrong(i-1)+i; // 不能調(diào)用,之前沒有return語句
else
return i; // 返回類型被推斷為int}
另一種類型推斷C++11中有兩種推斷類型的方式。 int i;int&& f();auto x3a = i; // x3a的類型是intdecltype(i) x3d = i; // x3d的類型是intauto x4a = (i); // x4a的類型是intdecltype((i)) x4d = (i); // x4d的類型是int&auto x5a = f(); // x5a的類型是intdecltype(f()) x5d = f(); // x5d的類型是int&& C++14增加了
放松的constexpr限制C++11引入了聲明為constexpr的函數(shù)的概念。聲明為constexpr函數(shù)的意義是:如果其參數(shù)均為合適的編譯期常量,則對(duì)這個(gè)constexpr函數(shù)的調(diào)用就可用于期望常量表達(dá)式的場(chǎng)合(如模板的非類型參數(shù),或枚舉常量的值)。如果參數(shù)的值在運(yùn)行期才能確定,或者雖然參數(shù)的值是編譯期常量,但不符合這個(gè)函數(shù)的要求,則對(duì)這個(gè)函數(shù)調(diào)用的求值只能在運(yùn)行期進(jìn)行。然而C++11要求constexpr函數(shù)只含有一個(gè)將被返回的表達(dá)式(也可以還含有 C++14將放松這些限制。聲明為constexpr的函數(shù)可以含有以下內(nèi)容:[8]
此外,C++11指出,所有被聲明為 變量模板在C++之前的版本中,模板可以是函數(shù)模板或類模板(C++11引入了類型別名模板)。C++14現(xiàn)在也可以創(chuàng)建變量模板。包括特化在內(nèi),通常的模板的規(guī)則都適用于變量模板的聲明和定義。[6][11] 聚合體成員初始化C++11新增member initializer,這是一個(gè)表達(dá)式,被應(yīng)用到類作用域的成員上,如果構(gòu)造函數(shù)沒有初始化這個(gè)成員。聚合體的定義被改為明確排除任何含有member initializer的類,因此,他們不允許使用聚合初始化。 C++14將放松這一限制,[8]這種類型也允許聚合初始化。如果花括號(hào)初始化列表不提供該參數(shù)的值,member initializer會(huì)初始化它。[12] 二進(jìn)制字面量C++14的數(shù)字可以用二進(jìn)制形式指定。[8]其格式使用前綴 數(shù)字分位符C++14引入單引號(hào)(')作為數(shù)字分位符號(hào),使得數(shù)值型的字面量可以具有更好的可讀性。[13] Ada、D語言、Java、Perl、Ruby等程序設(shè)計(jì)語言使用下劃線(_)作為數(shù)字分位符號(hào),C++之所以不和它們保持一致,是因?yàn)橄聞澗€已被用在用戶自定義的字面量的語法中。 auto integer_literal = 100'0000;auto floating_point_literal = 1.797'693'134'862'315'7E+308;auto binary_literal = 0b0100'1100'0110;auto silly_example = 1'0'0'000'00; 新的標(biāo)準(zhǔn)庫特性共享的互斥體和鎖C++14增加了一類共享的互斥體和相應(yīng)的共享鎖[14][15]。起初選擇的名字是 元函數(shù)的別名C++11定義了一組元函數(shù),用于查詢一個(gè)給定類型是否具有某種特征,或者轉(zhuǎn)換給定類型的某種特征,從而得到另一個(gè)類型。后一種元函數(shù)通過成員類型type來返回轉(zhuǎn)換后的類型,當(dāng)它們用在模板中時(shí),必須使用typename關(guān)鍵字,這會(huì)增加代碼的長(zhǎng)度。 template <class T>type_object< typename std::remove_cv< typename std::remove_reference<T>::type >::type>get_type_object(T&); 利用類型別名模板,C++14提供了更便捷的寫法。其命名規(guī)則是:如果標(biāo)準(zhǔn)庫的某個(gè)類模板(假設(shè)為 在C++14,擁有類型別名的元函數(shù)包括:remove_const、remove_volatile、remove_cv、add_const、add_volatile、add_cv、remove_reference、add_lvalue_reference、add_rvalue_reference、make_signed、make_unsigned、remove_extent、remove_all_extents、remove_pointer、add_pointer、aligned_storage、aligned_union、decay、 enable_if、conditional、common_type、underlying_type、result_of、tuple_element。 template <class T>type_object<std::remove_cv_t<std::remove_reference_t<T>>>get_type_object(T&); 關(guān)聯(lián)容器中的異構(gòu)查找C++標(biāo)準(zhǔn)庫定義了四個(gè)關(guān)聯(lián)容器類。set和multiset允許用戶根據(jù)一個(gè)值在容器中查找對(duì)應(yīng)的的同類型的值。map和multimap容器允許用戶指定鍵(key)和值(value)的類型,根據(jù)鍵進(jìn)行查找并返回對(duì)應(yīng)的值。然而,查找只能接受指定類型的參數(shù),在map和multimap中是鍵的類型,而在set和multiset容器中就是值本身的類型。 C++14允許通過其他類型進(jìn)行查找,只需要這個(gè)類型和實(shí)際的鍵類型之間可以進(jìn)行比較操作。[17]這允許 為保證向后兼容性,這種異構(gòu)查找只在提供給關(guān)聯(lián)容器的比較器允許的情況下有效。標(biāo)準(zhǔn)庫的泛型比較器,如 標(biāo)準(zhǔn)自定義字面量C++11增加了自定義字面量(user-defined literals)的特性,使用戶能夠定義新的字面量后綴,但標(biāo)準(zhǔn)庫并沒有對(duì)這一特性加以利用。C++14標(biāo)準(zhǔn)庫定義了以下字面量后綴:[17]
using namespace std::literals;std::string str = "hello world"s;std::chrono::seconds dur = 60s; 兩個(gè)"s"互不干擾,因?yàn)楸硎咀址闹荒軐?duì)字符串字面量操作,而表示秒的只針對(duì)數(shù)字。[19] 通過類型尋址多元組C++11引入的 tuple<string, string, int> t("foo", "bar", 7);int i = get<int>(t); // i == 7int j = get<2>(t); // Same as before: j == 7string s = get<string>(t); //Compiler error due to ambiguity
較小的標(biāo)準(zhǔn)庫特性
全局 已被移除或是不包含在C++14標(biāo)準(zhǔn)的特性因?yàn)镃++14的主要目的是漏洞修復(fù)和小的改進(jìn),一些重量級(jí)的特性被從C++14中移除,而移入各自的Technical Specification,并有可能合并入未來的C++17標(biāo)準(zhǔn)。 關(guān)于數(shù)組的擴(kuò)展以下特性將由Technical Specification—Array Extensions提供支持。[21] 在C++11和之前的標(biāo)準(zhǔn)中,在堆棧上分配的數(shù)組被限制為擁有一個(gè)固定的、編譯期確定的長(zhǎng)度。這一擴(kuò)展允許在堆棧上分配的一個(gè)數(shù)組的最后一維具有運(yùn)行期確定的長(zhǎng)度。[6] 運(yùn)行期確定長(zhǎng)度的數(shù)組不可以作為對(duì)象的一部分,也不可以具有全局存儲(chǔ)期,他們只能被聲明為局部變量。運(yùn)行期確定長(zhǎng)度的數(shù)組也可以使用C++11的基于范圍的for循環(huán)。[22] 同時(shí)還將添加 Optional值以下特性將由C++ Extensions for Library Fundamentals提供支持。[23] 類似于C#中的可空類型,optional類型可能含有或不含有一個(gè)值。這一類型基于Boost的 Concepts Lite參見: 概念 (C++)
被C++11拒絕后,Concepts受到徹底的修改。Concepts Lite是Concepts的一個(gè)部分,僅包含類型約束,而不含 |
|
|