日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > c/c++ >内容正文

c/c++

C++11中值得关注的几大变化

發(fā)布時(shí)間:2025/3/21 c/c++ 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C++11中值得关注的几大变化 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

賴(lài)勇浩(http://laiyonghao.com)
聲明:本文源自 Danny Kalev 在 2011 年 6 月 21 日發(fā)表的《The Biggest Changes in C++11(and Why You Should Care)》一文,幾乎所有內(nèi)容都搬了過(guò)來(lái),但不是全文照譯,有困惑之處,請(qǐng)參詳原文(http://www.softwarequalityconnection.com/2011/06/the-biggest-changes-in-c11-and-why-you-should-care/)。
注:作者 Danny Kalev 曾是 C++ 標(biāo)準(zhǔn)委員會(huì)成員。

Lambda 表達(dá)式

Lambda 表達(dá)式的形式是這樣的:

[cpp] view plain copy
  • [capture](parameters)->return-type?{body}??

  • 來(lái)看個(gè)計(jì)數(shù)某個(gè)字符序列中有幾個(gè)大寫(xiě)字母的例子:
    [cpp] view plain copy
  • int?main()??
  • {??
  • ???char?s[]="Hello?World!";??
  • ???int?Uppercase?=?0;?//modified?by?the?lambda??
  • ???for_each(s,?s+sizeof(s),?[&Uppercase]?(char?c)?{??
  • ????if?(isupper(c))??
  • ?????Uppercase++;??
  • ????});??
  • ?cout<<?Uppercase<<"?uppercase?letters?in:?"<<?s<<endl;??
  • }??

  • 其中 [&Uppercase] 中的 & 的意義是 lambda 函數(shù)體要獲取一個(gè) Uppercase 引用,以便能夠改變它的值,如果沒(méi)有 &,那就 Uppercase 將以傳值的形式傳遞過(guò)去。

    自動(dòng)類(lèi)型推導(dǎo)和 decltype

    在 C++03 中,聲明對(duì)象的同時(shí)必須指明其類(lèi)型,其實(shí)大多數(shù)情況下,聲明對(duì)象的同時(shí)也會(huì)包括一個(gè)初始值,C++11 在這種情況下就能夠讓你聲明對(duì)象時(shí)不再指定類(lèi)型了:

    [c-sharp] view plain copy
  • auto?x=0;?//0?是?int?類(lèi)型,所以?x?也是?int?類(lèi)型??
  • auto?c='a';?//char??
  • auto?d=0.5;?//double??
  • auto?national_debt=14400000000000LL;//long?long??

  • 這個(gè)特性在對(duì)象的類(lèi)型很大很長(zhǎng)的時(shí)候很有用,如:
    [cpp] view plain copy
  • void?func(const?vector<int>?&vi)??
  • {??
  • ??vector<int>::const_iterator?ci=vi.begin();??
  • }??

  • 那個(gè)迭代器可以聲明為:
    [cpp] view plain copy
  • auto?ci=vi.begin();??

  • C++11 也提供了從對(duì)象或表達(dá)式中“俘獲”類(lèi)型的機(jī)制,新的操作符 decltype 可以從一個(gè)表達(dá)式中“俘獲”其結(jié)果的類(lèi)型并“返回”:
    [c-sharp] view plain copy
  • const?vector<int>?vi;??
  • typedef?decltype?(vi.begin())?CIT;??
  • CIT?another_const_iterator;??
  • 統(tǒng)一的初始化語(yǔ)法

    C++ 最少有 4 種不同的初始化形式,如括號(hào)內(nèi)初始化,見(jiàn):

    [cpp] view plain copy
  • std::string?s("hello");??
  • int?m=int();?//default?initialization??

  • 還有等號(hào)形式的:
    [cpp] view plain copy
  • std::string?s="hello";??
  • int?x=5;??

  • 對(duì)于 POD 集合,又可以用大括號(hào):
    [cpp] view plain copy
  • int?arr[4]={0,1,2,3};??
  • struct?tm?today={0};??

  • 最后還有構(gòu)造函數(shù)的成員初始化:
    [cpp] view plain copy
  • struct?S?{??
  • ?int?x;??
  • ?S():?x(0)?{}?};??

  • 這么多初始化形式,不僅菜鳥(niǎo)會(huì)搞得很頭大,高手也吃不消。更慘的是 C++03 中居然不能初始化 POD 數(shù)組的類(lèi)成員,也不能在使用 new[] 的時(shí)候初始 POD 數(shù)組,操蛋啊!C++11 就用大括號(hào)一統(tǒng)天下了:
    [cpp] view plain copy
  • class?C??
  • {??
  • int?a;??
  • int?b;??
  • public:??
  • ?C(int?i,?int?j);??
  • };??
  • C?c?{0,0};?//C++11?only.?相當(dāng)于?C?c(0,0);??
  • int*?a?=?new?int[3]?{?1,?2,?0?};?/C++11?only??
  • class?X?{??
  • ??int?a[4];??
  • public:??
  • ??X()?:?a{1,2,3,4}?{}?//C++11,?初始化數(shù)組成員??
  • };??

  • 還有一大好事就是對(duì)于容器來(lái)說(shuō),終于可以擺脫 push_back() 調(diào)用了,C++11中可以直觀地初始化容器了:
    [cpp] view plain copy
  • //?C++11?container?initializer??
  • vector?vs<string>={?"first",?"second",?"third"};??
  • map?singers?=??
  • ??{?{"Lady?Gaga",?"+1?(212)?555-7890"},??
  • ????{"Beyonce?Knowles",?"+1?(212)?555-0987"}};??

  • 而類(lèi)中的數(shù)據(jù)成員初始化也得到了支持:
    [cpp] view plain copy
  • class?C??
  • {??
  • ?int?a=7;?//C++11?only??
  • public:??
  • ?C();??
  • };??
  • deleted 函數(shù)和 defaulted 函數(shù)

    像以下形式的函數(shù):

    [cpp] view plain copy
  • struct?A??
  • {??
  • ?A()=default;?//C++11??
  • ?virtual?~A()=default;?//C++11??
  • };??

  • 叫做 defaulted 函數(shù),=default; 指示編譯器生成該函數(shù)的默認(rèn)實(shí)現(xiàn)。這有兩個(gè)好處:一是讓程序員輕松了,少敲鍵盤(pán),二是有更好的性能。
    與 defaulted 函數(shù)相對(duì)的就是 deleted 函數(shù):
    [cpp] view plain copy
  • int?func()=delete;??

  • 這貨有一大用途就是實(shí)現(xiàn) noncopyabe 防止對(duì)象拷貝,要想禁止拷貝,用 =deleted 聲明一下兩個(gè)關(guān)鍵的成員函數(shù)就可以了:
    [cpp] view plain copy
  • struct?NoCopy??
  • {??
  • ????NoCopy?&?operator?=(?const?NoCopy?&?)?=?delete;??
  • ????NoCopy?(?const?NoCopy?&?)?=?delete;??
  • };??
  • NoCopy?a;??
  • NoCopy?b(a);?//編譯錯(cuò)誤,拷貝構(gòu)造函數(shù)是?deleted?函數(shù)??
  • nullptr

    nullptr 是一個(gè)新的 C++ 關(guān)鍵字,它是空指針常量,它是用來(lái)替代高風(fēng)險(xiǎn)的 NULL 宏和 0 字面量的。nullptr 是強(qiáng)類(lèi)型的:

    [cpp] view plain copy
  • void?f(int);?//#1??
  • void?f(char?*);//#2??
  • //C++03??
  • f(0);?//調(diào)用的是哪個(gè)?f???
  • //C++11??
  • f(nullptr)?//毫無(wú)疑問(wèn),調(diào)用的是?#2??

  • 所有跟指針有關(guān)的地方都可以用 nullptr,包括函數(shù)指針和成員指針:
    [cpp] view plain copy
  • const?char?*pc=str.c_str();?//data?pointers??
  • if?(pc!=nullptr)??
  • ??cout<<pc<<endl;??
  • int?(A::*pmf)()=nullptr;?//指向成員函數(shù)的指針??
  • void?(*pmf)()=nullptr;?//指向函數(shù)的指針??
  • 委托構(gòu)造函數(shù)

    C++11 中構(gòu)造函數(shù)可以調(diào)用同一個(gè)類(lèi)的另一個(gè)構(gòu)造函數(shù):

    [cpp] view plain copy
  • class?M?//C++11?delegating?constructors??
  • {??
  • ?int?x,?y;??
  • ?char?*p;??
  • public:??
  • ?M(int?v)?:?x(v),?y(0),??p(new?char?[MAX])??{}?//#1?target??
  • ?M():?M(0)?{cout<<"delegating?ctor"<<end;}?//#2?delegating??

  • #2 就是所謂的委托構(gòu)造函數(shù),調(diào)用了真正的構(gòu)造函數(shù) #1。

    右值引用

    在 C++03 中的引用類(lèi)型是只綁定左值的,C++11 引用一個(gè)新的引用類(lèi)型叫右值引用類(lèi)型,它是綁定到右值的,如臨時(shí)對(duì)象或字面量。
    增加右值引用的主要原因是為了實(shí)現(xiàn) move 語(yǔ)義。與傳統(tǒng)的拷貝不同,move 的意思是目標(biāo)對(duì)象“竊取”原對(duì)象的資源,并將源置于“空”狀態(tài)。當(dāng)拷貝一個(gè)對(duì)象時(shí),其實(shí)代價(jià)昂貴且無(wú)必要,move 操作就可以替代它。如在 string 交換的時(shí)候,使用 move 意義就有巨大的性能提升,如原方案是這樣的:

    [cpp] view plain copy
  • void?naiveswap(string?&a,?string?&?b)??
  • {??
  • ?string?temp?=?a;??
  • ?a=b;??
  • ?b=temp;??
  • }??

  • 這種方案很傻很天真,很慢,因?yàn)樾枰暾?qǐng)內(nèi)存,然后拷貝字符,而 move 就只需要交換兩個(gè)數(shù)據(jù)成員,無(wú)須申請(qǐng)、釋放內(nèi)存和拷貝字符數(shù)組:
    [cpp] view plain copy
  • void?moveswapstr(string&?empty,?string?&?filled)??
  • {??
  • //pseudo?code,?but?you?get?the?idea??
  • ?size_t?sz=empty.size();??
  • ?const?char?*p=?empty.data();??
  • //move?filled's?resources?to?empty??
  • ?empty.setsize(filled.size());??
  • ?empty.setdata(filled.data());??
  • //filled?becomes?empty??
  • ?filled.setsize(sz);??
  • ?filled.setdata(p);??
  • }??

  • 要實(shí)現(xiàn)支持 move 的類(lèi),需要聲明 move 構(gòu)造函數(shù)和 move 賦值操作符,如下:
    [cpp] view plain copy
  • class?Movable??
  • {??
  • Movable?(Movable&&);?//move?constructor??
  • Movable&&?operator=(Movable&&);?//move?assignment?operator??
  • };??

  • C++11 的標(biāo)準(zhǔn)庫(kù)廣泛使用 move 語(yǔ)義,很多算法和容器都已經(jīng)使用 move 語(yǔ)義優(yōu)化過(guò)了。

    C++11 的標(biāo)準(zhǔn)庫(kù)

    除 TR1 包含的新容器(unordered_set, unordered_map, unordered_multiset, 和unordered_multimap),還有一些新的庫(kù),如正則表達(dá)式,tuple,函數(shù)對(duì)象封裝器等。下面介紹一些 C++11 的標(biāo)準(zhǔn)庫(kù)新特性:

    線程庫(kù)

    從程序員的角度來(lái)看,C++11 最重要的特性就是并發(fā)了。C++11 提供了 thread 類(lèi),也提供了 promise 和 future 用以并發(fā)環(huán)境中的同步,用 async() 函數(shù)模板執(zhí)行并發(fā)任務(wù),和 thread_local 存儲(chǔ)聲明為特定線程獨(dú)占的數(shù)據(jù),這里(http://www.devx.com/SpecialReports/Article/38883)有一個(gè)簡(jiǎn)單的 C++11 線程庫(kù)教程(英文)。

    新的智能指針類(lèi)

    C++98 定義的唯一的智能指針類(lèi) auto_ptr 已經(jīng)被棄用,C++11 引入了新的智能針對(duì)類(lèi) shared_ptr 和 unique_ptr。它們都是標(biāo)準(zhǔn)庫(kù)的其它組件兼容,可以安全地把智能指針存入標(biāo)準(zhǔn)容器,也可以安全地用標(biāo)準(zhǔn)算法“倒騰”它們。

    新的算法

    主要是 all_of()、any_of() 和 none_of(),下面是例子:

    [cpp] view plain copy
  • #include?<algorithm>??
  • //C++11?code??
  • //are?all?of?the?elements?positive???
  • all_of(first,?first+n,?ispositive());?//false??
  • //is?there?at?least?one?positive?element???
  • any_of(first,?first+n,?ispositive());//true??
  • //?are?none?of?the?elements?positive???
  • none_of(first,?first+n,?ispositive());?//false??

  • 還有一個(gè)新的 copy_n:
    [cpp] view plain copy
  • #include?<algorithm>??
  • int?source[5]={0,12,34,50,80};??
  • int?target[5];??
  • //從?source?拷貝?5?個(gè)元素到?target??
  • copy_n(source,5,target);??

  • iota() 算法可以用來(lái)創(chuàng)建遞增序列,它先把初值賦值給 *first,然后用前置 ++ 操作符增長(zhǎng)初值并賦值到給下一個(gè)迭代器指向的元素,如下:
    [cpp] view plain copy
  • #include?<numeric>??
  • int?a[5]={0};??
  • char?c[3]={0};??
  • iota(a,?a+5,?10);?//changes?a?to?{10,11,12,13,14}??
  • iota(c,?c+3,?'a');?//{'a','b','c'}??

  • 是的,C++11 仍然缺少一些很有用的庫(kù)如 XML API,socket,GUI、反射——以及自動(dòng)垃圾收集。然而現(xiàn)有特性已經(jīng)讓 C++ 更安全、高效(是的,效率更高了,可以參見(jiàn) Google 的 基準(zhǔn)測(cè)試結(jié)果http://www.itproportal.com/2011/06/07/googles-rates-c-most-complex-highest-performing-language/)以及更加易于學(xué)習(xí)和使用。
    如果覺(jué)得 C++ 變化太大了,不必驚恐,花點(diǎn)時(shí)間來(lái)學(xué)習(xí)就好了。可能在你融會(huì)貫通新特性以后,你會(huì)同意 Stroustrup 的觀點(diǎn):C++11 是一門(mén)新的語(yǔ)言——一個(gè)更好的 C++。

    總結(jié)

    以上是生活随笔為你收集整理的C++11中值得关注的几大变化的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。