C++11中值得关注的几大变化
賴勇浩(http://laiyonghao.com)
聲明:本文源自 Danny Kalev 在 2011 年 6 月 21 日發(fā)表的《The Biggest Changes in C++11(and Why You Should Care)》一文,幾乎所有內(nèi)容都搬了過來,但不是全文照譯,有困惑之處,請參詳原文(http://www.softwarequalityconnection.com/2011/06/the-biggest-changes-in-c11-and-why-you-should-care/)。
注:作者 Danny Kalev 曾是 C++ 標(biāo)準(zhǔn)委員會成員。
Lambda 表達(dá)式
Lambda 表達(dá)式的形式是這樣的:
來看個(gè)計(jì)數(shù)某個(gè)字符序列中有幾個(gè)大寫字母的例子:
[cpp] view plain copy
其中 [&Uppercase] 中的 & 的意義是 lambda 函數(shù)體要獲取一個(gè) Uppercase 引用,以便能夠改變它的值,如果沒有 &,那就 Uppercase 將以傳值的形式傳遞過去。
自動類型推導(dǎo)和 decltype
在 C++03 中,聲明對象的同時(shí)必須指明其類型,其實(shí)大多數(shù)情況下,聲明對象的同時(shí)也會包括一個(gè)初始值,C++11 在這種情況下就能夠讓你聲明對象時(shí)不再指定類型了:
這個(gè)特性在對象的類型很大很長的時(shí)候很有用,如:
[cpp] view plain copy
那個(gè)迭代器可以聲明為:
[cpp] view plain copy
C++11 也提供了從對象或表達(dá)式中“俘獲”類型的機(jī)制,新的操作符 decltype 可以從一個(gè)表達(dá)式中“俘獲”其結(jié)果的類型并“返回”:
[c-sharp] view plain copy
統(tǒng)一的初始化語法
C++ 最少有 4 種不同的初始化形式,如括號內(nèi)初始化,見:
還有等號形式的:
[cpp] view plain copy
對于 POD 集合,又可以用大括號:
[cpp] view plain copy
最后還有構(gòu)造函數(shù)的成員初始化:
[cpp] view plain copy
這么多初始化形式,不僅菜鳥會搞得很頭大,高手也吃不消。更慘的是 C++03 中居然不能初始化 POD 數(shù)組的類成員,也不能在使用 new[] 的時(shí)候初始 POD 數(shù)組,操蛋啊!C++11 就用大括號一統(tǒng)天下了:
[cpp] view plain copy
還有一大好事就是對于容器來說,終于可以擺脫 push_back() 調(diào)用了,C++11中可以直觀地初始化容器了:
[cpp] view plain copy
而類中的數(shù)據(jù)成員初始化也得到了支持:
[cpp] view plain copy
deleted 函數(shù)和 defaulted 函數(shù)
像以下形式的函數(shù):
叫做 defaulted 函數(shù),=default; 指示編譯器生成該函數(shù)的默認(rèn)實(shí)現(xiàn)。這有兩個(gè)好處:一是讓程序員輕松了,少敲鍵盤,二是有更好的性能。
與 defaulted 函數(shù)相對的就是 deleted 函數(shù):
[cpp] view plain copy
這貨有一大用途就是實(shí)現(xiàn) noncopyabe 防止對象拷貝,要想禁止拷貝,用 =deleted 聲明一下兩個(gè)關(guān)鍵的成員函數(shù)就可以了:
[cpp] view plain copy
nullptr
nullptr 是一個(gè)新的 C++ 關(guān)鍵字,它是空指針常量,它是用來替代高風(fēng)險(xiǎn)的 NULL 宏和 0 字面量的。nullptr 是強(qiáng)類型的:
所有跟指針有關(guān)的地方都可以用 nullptr,包括函數(shù)指針和成員指針:
[cpp] view plain copy
委托構(gòu)造函數(shù)
C++11 中構(gòu)造函數(shù)可以調(diào)用同一個(gè)類的另一個(gè)構(gòu)造函數(shù):
#2 就是所謂的委托構(gòu)造函數(shù),調(diào)用了真正的構(gòu)造函數(shù) #1。
右值引用
在 C++03 中的引用類型是只綁定左值的,C++11 引用一個(gè)新的引用類型叫右值引用類型,它是綁定到右值的,如臨時(shí)對象或字面量。
增加右值引用的主要原因是為了實(shí)現(xiàn) move 語義。與傳統(tǒng)的拷貝不同,move 的意思是目標(biāo)對象“竊取”原對象的資源,并將源置于“空”狀態(tài)。當(dāng)拷貝一個(gè)對象時(shí),其實(shí)代價(jià)昂貴且無必要,move 操作就可以替代它。如在 string 交換的時(shí)候,使用 move 意義就有巨大的性能提升,如原方案是這樣的:
這種方案很傻很天真,很慢,因?yàn)樾枰暾垉?nèi)存,然后拷貝字符,而 move 就只需要交換兩個(gè)數(shù)據(jù)成員,無須申請、釋放內(nèi)存和拷貝字符數(shù)組:
[cpp] view plain copy
要實(shí)現(xiàn)支持 move 的類,需要聲明 move 構(gòu)造函數(shù)和 move 賦值操作符,如下:
[cpp] view plain copy
C++11 的標(biāo)準(zhǔn)庫廣泛使用 move 語義,很多算法和容器都已經(jīng)使用 move 語義優(yōu)化過了。
C++11 的標(biāo)準(zhǔn)庫
除 TR1 包含的新容器(unordered_set, unordered_map, unordered_multiset, 和unordered_multimap),還有一些新的庫,如正則表達(dá)式,tuple,函數(shù)對象封裝器等。下面介紹一些 C++11 的標(biāo)準(zhǔn)庫新特性:
線程庫
從程序員的角度來看,C++11 最重要的特性就是并發(fā)了。C++11 提供了 thread 類,也提供了 promise 和 future 用以并發(fā)環(huán)境中的同步,用 async() 函數(shù)模板執(zhí)行并發(fā)任務(wù),和 thread_local 存儲聲明為特定線程獨(dú)占的數(shù)據(jù),這里(http://www.devx.com/SpecialReports/Article/38883)有一個(gè)簡單的 C++11 線程庫教程(英文)。
新的智能指針類
C++98 定義的唯一的智能指針類 auto_ptr 已經(jīng)被棄用,C++11 引入了新的智能針對類 shared_ptr 和 unique_ptr。它們都是標(biāo)準(zhǔn)庫的其它組件兼容,可以安全地把智能指針存入標(biāo)準(zhǔn)容器,也可以安全地用標(biāo)準(zhǔn)算法“倒騰”它們。
新的算法
主要是 all_of()、any_of() 和 none_of(),下面是例子:
還有一個(gè)新的 copy_n:
[cpp] view plain copy
iota() 算法可以用來創(chuàng)建遞增序列,它先把初值賦值給 *first,然后用前置 ++ 操作符增長初值并賦值到給下一個(gè)迭代器指向的元素,如下:
[cpp] view plain copy
是的,C++11 仍然缺少一些很有用的庫如 XML API,socket,GUI、反射——以及自動垃圾收集。然而現(xiàn)有特性已經(jīng)讓 C++ 更安全、高效(是的,效率更高了,可以參見 Google 的 基準(zhǔn)測試結(jié)果http://www.itproportal.com/2011/06/07/googles-rates-c-most-complex-highest-performing-language/)以及更加易于學(xué)習(xí)和使用。
如果覺得 C++ 變化太大了,不必驚恐,花點(diǎn)時(shí)間來學(xué)習(xí)就好了。可能在你融會貫通新特性以后,你會同意 Stroustrup 的觀點(diǎn):C++11 是一門新的語言——一個(gè)更好的 C++。
總結(jié)
以上是生活随笔為你收集整理的C++11中值得关注的几大变化的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 用BP人工神经网络识别手写数字——《Py
- 下一篇: 关于Python编程的一些问答