小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

C++14新特性

 碼農(nóng)書館 2021-02-09

C++14C++的現(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。[3]

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ù)lambda的返回值是1,說明value被初始化為1。被聲明的捕獲變量的類型會(huì)根據(jù)初始化表達(dá)式推斷,推斷方式與用auto聲明變量相同。

使用標(biāo)準(zhǔn)函數(shù)std::move可以使之被用以通過move捕獲:

auto ptr = std::make_unique<int>(10); //See below for std::make_uniqueauto lambda = [ptr = std::move(ptr)] {return *ptr;}

聲明ptr = std::move(ptr)使用了兩次ptr。第一次使用聲明了一個(gè)新的變量,但在捕獲部分,這個(gè)變量還不在作用域內(nèi)。所以第二個(gè)ptr表示之前在lambda之外聲明的變量。[7]

函數(shù)返回類型推導(dǎo)

C++11允許lambda函數(shù)根據(jù)return語句的表達(dá)式類型推斷返回類型。C++14為一般的函數(shù)也提供了這個(gè)能力。C++14還拓展了原有的規(guī)則,使得函數(shù)體并不是{return ;}形式的函數(shù)也可以使用返回類型推導(dǎo)。[8]

為了啟用返回類型推導(dǎo),函數(shù)聲明必須將auto作為返回類型,但沒有C++11的后置返回類型說明符:

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中有兩種推斷類型的方式。auto根據(jù)給出的表達(dá)式產(chǎn)生具有合適類型的變量。decltype可以計(jì)算給出的表達(dá)式的類型。但是,decltypeauto推斷類型的方式是不同的。特別地,auto總是推斷出非引用類型,就好像使用了std::remove_reference一樣,而auto&&總是推斷出引用類型。然而decltype可以根據(jù)表達(dá)式的值類別(value category)和表達(dá)式的性質(zhì)推斷出引用或非引用類型:[8]

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增加了decltype(auto)的語法。這允許不必顯式指定作為decltype參數(shù)的表達(dá)式,而使用decltype對(duì)于給定表達(dá)式的推斷規(guī)則。

decltype(auto)的語法也可以用于返回類型推導(dǎo),只需用decltype(auto)代替auto。[9]

放松的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á)式(也可以還含有static_assert聲明等其它語句,但允許的語句類型很少)。

C++14將放松這些限制。聲明為constexpr的函數(shù)可以含有以下內(nèi)容:[8]

  • 任何聲明,除了:

    • staticthread_local變量。

    • 沒有初始化的變量聲明。

  • 條件分支語句ifswitch。

  • 所有的循環(huán)語句,包括基于范圍的for循環(huán)。

  • 表達(dá)式可以改變一個(gè)對(duì)象的值,只需該對(duì)象的生命期在聲明為constexpr的函數(shù)內(nèi)部開始。包括對(duì)有constexpr聲明的任何非const非靜態(tài)成員函數(shù)的調(diào)用。

goto仍然不允許在constexpr函數(shù)中出現(xiàn)。

此外,C++11指出,所有被聲明為constexpr的非靜態(tài)成員函數(shù)也隱含聲明為const(即函數(shù)不能修改*this的值)。這點(diǎn)已經(jīng)被刪除,非靜態(tài)成員函數(shù)可以為非const。[10]

變量模板

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]其格式使用前綴0b0B。這樣的語法也被JavaPython、PerlD語言使用。

數(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]。起初選擇的名字是std::shared_mutex,但由于后來增加了與std::timed_mutex相似的特性,std::shared_timed_mutex成為了更適合的名字。[16]

元函數(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è)為std::some_class)只含有唯一的成員,即成員類型type,那么標(biāo)準(zhǔn)庫提供std::some_class_t<T>作為typename std::some_class::type的別名。

在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]這允許std::set<std::string>使用const char*,或任何可以通過operator< 與std::string比較的類型作為查找的參數(shù)。

為保證向后兼容性,這種異構(gòu)查找只在提供給關(guān)聯(lián)容器的比較器允許的情況下有效。標(biāo)準(zhǔn)庫的泛型比較器,如std::less<>std::greater<>允許異構(gòu)查找。[18]

標(biāo)準(zhǔn)自定義字面量

C++11增加了自定義字面量(user-defined literals)的特性,使用戶能夠定義新的字面量后綴,但標(biāo)準(zhǔn)庫并沒有對(duì)這一特性加以利用。C++14標(biāo)準(zhǔn)庫定義了以下字面量后綴:[17]

  • "s",用于創(chuàng)建各種std::basic_string類型。

  • "h"、"min"、"s"、"ms"、"us"、"ns",用于創(chuàng)建相應(yīng)的std::chrono::duration時(shí)間間隔。

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引入的std::tuple類型允許不同類型的值的聚合體用編譯期整型常數(shù)索引。C++14還允許使用類型代替常數(shù)索引,從多元組中獲取對(duì)象。[17]若多元組含有多于一個(gè)這個(gè)類型的對(duì)象,將會(huì)產(chǎn)生一個(gè)編譯錯(cuò)誤:[20]

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)庫特性

std::make_unique可以像std::make_shared一樣使用,用于產(chǎn)生std::unique_ptr對(duì)象。[6]

std::is_final,用于識(shí)別一個(gè)class類型是否禁止被繼承。

std::integral_constant增加了一個(gè)返回常量值的operator()。[17]

全局std::begin/std::end函數(shù)之外,增加了std::cbegin/std::cend函數(shù),它們總是返回常量迭代器(constant iterators)。

已被移除或是不包含在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í)還將添加std::dynarray類型,它擁有與std::vectorstd::array相似的接口。代表一個(gè)固定長(zhǎng)度的數(shù)組,其大小在運(yùn)行期構(gòu)造對(duì)象時(shí)確定。std::dynarray類被明顯地設(shè)計(jì)為當(dāng)它被放置在棧上時(shí)(直接放置在棧上,或作為另一個(gè)棧對(duì)象的成員),可以使用棧內(nèi)存而不是堆內(nèi)存。

Optional值

以下特性將由C++ Extensions for Library Fundamentals提供支持。[23]

類似于C#中的可空類型,optional類型可能含有或不含有一個(gè)值。這一類型基于Boostboost::optional類,而添加了C++11和C++14中的新特性,諸如移動(dòng)和in-place構(gòu)造。它不允許用在引用類型上。這個(gè)類被專門的設(shè)計(jì)為一個(gè)literal type(如果模板參數(shù)本身是一個(gè)literal type),因此,它在必要的情況下含有constexpr構(gòu)造函數(shù)。[24]

Concepts Lite

參見: 概念 (C++)

被C++11拒絕后,Concepts受到徹底的修改。Concepts Lite是Concepts的一個(gè)部分,僅包含類型約束,而不含concept_mapaxiom[25]。它將在一個(gè)單獨(dú)的Technical Specification中發(fā)展,并有可能加入C++17。

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多