|
來源 :今日頭條@Hu先生Linux后臺開發(fā) C++ 有一些新特性非常好用,本文對此進(jìn)行了介紹,比如 auto、lambda、constexpr、tuple、智能指針等。 當(dāng)然,這些改變不是一夜之間發(fā)生的。曾幾何時,C++缺乏活力,導(dǎo)致人們不太喜歡這門語言。 但是,當(dāng) C++標(biāo)準(zhǔn)委員會決定加快轉(zhuǎn)變時,情況就不同了。 不要誤以為是這門語言變得簡單了,實際并沒有。它仍然是被廣泛使用的最難編程語言之一。但是相比于之前的版本,確實對用戶更加友好了。 今天,我們深入發(fā)掘一下每位開發(fā)者都應(yīng)該了解的新特性(這些新特性從 C++11 時開始出現(xiàn),距今已有八年歷史了)。注意,本文略過了一些高級特性,可能會在以后的內(nèi)容中詳細(xì)探討。 auto 概念 當(dāng) C++11 第一次引入 auto,一切都變得更簡單了。 auto 的概念是讓 c++編譯器在編譯時自動推斷數(shù)據(jù)的類型,而不是每次都要求你手動聲明類型。如果你的數(shù)據(jù)類型是 map<string,vector<pair<int,int>>> 看一下第五行。沒有 initializer 時你不能聲明某些東西,這不難理解。像第五行這樣,編譯器是無法推斷數(shù)據(jù)類型的。 最初,auto 的使用是非常受限的。在之后的版本中,auto 變得更加強大! 第 7 和第 8 行中,我使用了花括號初始化。這個特性也是 C++11 中新加入的。 實際上,C++11 引入了 std::initializer_list<type>,如果聲明為 auto,那么初始化列表會被認(rèn)為是這種輕量級容器。 最后,就像前面提到的,當(dāng)你使用復(fù)雜的數(shù)據(jù)類型時,編譯器推斷數(shù)據(jù)類型會非常有用。 不要忘記查看第 25 行!表達(dá)式 auto [v1,v2] = itr.second 是 C++17 的新特性。這被稱為結(jié)構(gòu)化綁定。在之前的版本中,每個變量必須要分別進(jìn)行提取,然而結(jié)構(gòu)化綁定會使這個過程方便很多。 另外,如果你想通過引用獲取數(shù)據(jù),只需要添加一個像 auto &[v1,v2] = itr.second 這樣的符號,非常簡潔。 lambda 表達(dá)式 C++11 引入了 lambda 表達(dá)式,該表達(dá)式和 JavaScript 中的匿名函數(shù)非常相似。它們是沒有命名的函數(shù)對象,并且基于一些簡潔的語法在不同的作用域捕獲變量,它們還可以分配給變量。 當(dāng)你想在代碼中快速實現(xiàn)一些小功能但并不想為此單獨編寫整個函數(shù)時,lambda 非常有用。另一種非常普遍的應(yīng)用是將其作為比較函數(shù)。 上面的例子中有很多細(xì)節(jié)。 首先,要注意到列表初始化為你節(jié)省了多少代碼。然后是通用的 begin() 和 end(),它們同樣也是 C++11 中新添加的。然后是作為數(shù)據(jù)比較器的 lambda 函數(shù)。lambda 函數(shù)的參數(shù)被聲明為 auto,這是 c++14 中新增的。在此之前,是不可以用 auto 作為函數(shù)參數(shù)的。 這里使用方括號[]作為 lambda 表達(dá)式的開始。它定義了 lambda 函數(shù)的作用域,即它對局部變量和對象有多少權(quán)限。 下面是一些現(xiàn)代 c++中的相關(guān)定義: []代表空。因此你不可以在 lambda 表達(dá)式中使用任何外部作用域的局部變量。只可以使用參數(shù)。 [=]代表可通過值獲取作用域內(nèi)的局部對象(局部變量和參數(shù)),即你只可以使用但不可修改。 [&]代表可通過引用獲取作用域內(nèi)的局部對象(局部變量和參數(shù)),即你可以像下面例子中一樣修改它。 [this]代表可通過值獲取 this 指針。 [a,&b]代表通過值獲取對象 a, 通過引用獲取對象 b。 在上面的例子中,如果你在 lambda 表達(dá)式中使用 [factor] 取值的方式獲取了局部變量,你就不能在第五行中修改 factor,因為你沒有權(quán)利這樣做。不要濫用你的權(quán)限! 最后,注意這里 var 是引用。這保證了在 lambda 函數(shù)內(nèi)的任何改變都會真正改變 vector。 if 或 switch 語句里的初始狀態(tài) 當(dāng)我了解了 c++17 的這個特性之后我非常喜歡。 顯然,現(xiàn)在你可以在 if/switch 語句塊內(nèi)初始化變量并且進(jìn)行條件檢查了。這對保持代碼的緊湊和簡潔是非常有幫助的。通常形式如下: 編譯時執(zhí)行 constexpr constexpr 非常酷! 假設(shè)你有一些表達(dá)式要計算,并且它的值一旦初始化就不會改變。你可以預(yù)先計算該值并且作為宏來使用?;蛘呦?C++11 中提供的,你可以使用 constexpr。 上面的代碼是 constexpr 的一個常見例子。 由于我們聲明 fibonacci 計算函數(shù)為 constexpr,編譯器會在編譯時預(yù)先計算 fib(20) 的值。所以編譯結(jié)束后,它可以把 const long long bigval = fib(20) 替換為 const long long bigval = 2432902008176640000; 需要注意的是,傳遞的參數(shù)是 const 值。這是聲明為 constexpr 的函數(shù)非常重要的一點,傳遞的參數(shù)同樣要是 constexpr 或者 const。否則,該函數(shù)會像普通函數(shù)一樣執(zhí)行,即不會在編譯時預(yù)先計算。 變量也同樣可以是 constexpr。這種情況下,你應(yīng)該可以猜到,這些變量同樣也是編譯時計算的。否則,會出現(xiàn)編譯錯誤。 有趣的是,在之后的 c++17 中,又引入了 constexpr-if 和 constexpr-lambda。 tuple 和 pair 非常相似,tuple 是一組各種數(shù)據(jù)類型的固定大小值的集合。 有時候,使用std::array會比使用 tuple 更加方便。array 和普通 C 類型的 array 非常相似,但具有 C++標(biāo)準(zhǔn)庫的一些特性。這種數(shù)據(jù)結(jié)構(gòu)是 C++11 中新增的。 類模版參數(shù)推斷 名字有點長。從 c++17 開始,參數(shù)推斷也適用于標(biāo)準(zhǔn)類模版。此前,該特性只支持函數(shù)模版。 因此, 類型推斷是隱式完成的。這對 tuple 來說變得更加方便。 ![]() 如果你不熟悉 C++模版,那么上述特性可能對你來說不是很好理解。 智能指針 指針也可能并不好用。 由于C++給編程人員提供了很大的自由度,有時這種自由可能反而會成為絆腳石。在多數(shù)情況下,都是指針在起反面作用。 幸運的是,C++11 引入了智能指針,它比之前的原始指針更加方便,可以通過適當(dāng)?shù)刂羔樶尫艓椭_發(fā)者避免內(nèi)存泄漏,同時也提供了額外的安全機制。 |
|
|
來自: 西北望msm66g9f > 《編程》