日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

C++ 學(xué)習(xí)筆記(一些新特性總結(jié) 1)

 imelee 2018-04-10

雖然我也用了 C++ 有挺多年了,但是一直本著夠用就行的原則,沒(méi)有特別深入的學(xué)習(xí)過(guò)C++ 的語(yǔ)法,所以好多高級(jí)的 C++ 特性都不了解。正好最近從網(wǎng)上找到了本書(shū)《C++ 14 Quick Syntax Reference》,挺薄的一本書(shū),只有 100多頁(yè),但是覆蓋了基本所有 C++ 的特性。這個(gè)小短文就是我看這本書(shū)時(shí)摘抄下來(lái)的一些我以前沒(méi)有注意到的知識(shí)點(diǎn)。

文中所有代碼都在 gcc version 5.3.0 (Rev1, Built by MSYS2 project) 上測(cè)試通過(guò)。

16進(jìn)制、8進(jìn)制、2進(jìn)制表示

int myOct = 062;
int myHex = 0x32;
int myBin = 0b00110010;
  • 1
  • 2
  • 3
  • 4

其中 16進(jìn)制、8進(jìn)制表示法是很早就支持的特性。2進(jìn)制表示是 C++14 才正式支持的。
除此之外,C++14 還引入了單引號(hào)作為數(shù)字表示的分隔符。方便我們閱讀很長(zhǎng)的數(shù)字。比如下面這個(gè)例子:

int longBin = 0b1010'0101'1010'0101;
  • 1
  • 2

加了三個(gè)單引號(hào)作為分割,讀起來(lái)就方便多了。

NULL 指針(nullptr)

早期的 C++ 中,我們用 0 或者 NULL 來(lái)表示無(wú)效的指針地址。C++11 專(zhuān)門(mén)引入了一個(gè)新的關(guān)鍵字 nullptr 來(lái)表示 NULL 指針。

int* p = nullptr; // ok
  • 1
  • 2

并且 nullptr 還是有類(lèi)型的,類(lèi)型為 nullptr_t:

nullptr_t mynull = nullptr; // ok
  • 1
  • 2

右值引用類(lèi)型(C++11)

左值和右值都是針對(duì)表達(dá)式而言的,左值是指表達(dá)式結(jié)束后依然存在的持久對(duì)象,右值是指表達(dá)式結(jié)束時(shí)就不再存在的臨時(shí)對(duì)象。

所謂右值引用就是引用一個(gè)右值對(duì)象(臨時(shí)對(duì)象),比如下面的例子:

int&& ref = 1 + 2; // rvalue reference
ref += 3;
cout << ref; // "6"
  • 1
  • 2
  • 3
  • 4

ref 對(duì)應(yīng)的是 1+2的結(jié)果3,這是個(gè)臨時(shí)對(duì)象。傳統(tǒng)的C++引用方式是無(wú)法引用到這個(gè)臨時(shí)對(duì)象的。右值引用主要是解決效率問(wèn)題,具體的方法可以搜索 “C++ 移動(dòng)語(yǔ)義”。

原生字符串(raw string literals)

raw string 可以取消轉(zhuǎn)義字符的作用,是 C++11 中添加的新特性。比如:

string escaped = "c:\\Windows\\System32\\cmd.exe";
  • 1
  • 2

可以簡(jiǎn)寫(xiě)為:

string raw = R"(c:\Windows\System32\cmd.exe)";  
  • 1
  • 2

RAW String 開(kāi)頭要用大寫(xiě)的 R ,然后在雙引號(hào)內(nèi)要增加一對(duì)括號(hào)。

這個(gè)功能在其他的語(yǔ)言中早就有了。我們上邊這個(gè)例子還不大能看出 raw string 的優(yōu)勢(shì),但是如果常寫(xiě)正則表達(dá)式的話(huà),就會(huì)感覺(jué) raw string 太方便了。比如:

char str[] = R"(('(?:[^\\']|\\.)*'|"(?:[^\\"]|\\.)*")|)";
  • 1
  • 2

舊的寫(xiě)法是:

char oldstr[] = "('(?:[^\\\\']|\\\\.)*'|\"(?:[^\\\\\"]|\\\\.)*\")|";
  • 1
  • 2

新的 char 類(lèi)型

C++ 11 中引入了 char16_t 和 char32_t 兩種類(lèi)型。這兩種字符類(lèi)型可以分別用來(lái)存儲(chǔ) utf-16 和 utf-32 編碼的字符。相應(yīng)的 string 類(lèi)型也有兩個(gè)變種, u16string 和u32string。

string s3 = u8"UTF-8 string";
u16string s4 = u"UTF-16 string";
u32string s5 = U"UTF-32 string";
  • 1
  • 2
  • 3
  • 4

字符串前的 u8、u和 U也是新增的特性,分別用來(lái)支持 UTF-8、UTF-16和UTF-32 字符串。

for 循環(huán)

C++11 對(duì) for 循環(huán)做了擴(kuò)展,for 循環(huán)支持一種新的語(yǔ)法。

int a[3] = {1, 2, 3};
for (int &i : a) 
{
    cout <<i; // "123"
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

auto 和 decltype 關(guān)鍵字

這兩個(gè)關(guān)鍵字都是 C++ 11 中引入的。auto 關(guān)鍵字告訴編譯器自動(dòng)推導(dǎo)變量的類(lèi)型。比如下面的代碼:

auto i = 5; // int
auto d = 3.14; // double
auto b = false; // bool
  • 1
  • 2
  • 3
  • 4

如果我們希望推導(dǎo)出的類(lèi)型是引用類(lèi)型。那么需要在 auto 之后加個(gè) &。比如下面這樣:

int& iRef = i;
auto myAuto = iRef; // int
auto& myRef = iRef; // int&
  • 1
  • 2
  • 3
  • 4

用 auto 之后可以簡(jiǎn)化許多代碼。比如下面這個(gè)代碼:

vector<int> myVector { 1, 2, 3 };
for(vector<int>::size_type i = 0; i != myVector.size(); i++) 
{
    cout << myVector[i]; 
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

用 auto 的話(huà)可以寫(xiě)為:

for(auto i = 0; i != myVector.size(); i++) 
{
    cout << myVector[i]; 
}
  • 1
  • 2
  • 3
  • 4
  • 5

當(dāng)然,用上 for 的新語(yǔ)法,還可以寫(xiě)的更簡(jiǎn)便:

for (auto& x : myVector) 
{ 
    cout << x << endl; 
} 
  • 1
  • 2
  • 3
  • 4
  • 5

decltype 與 auto 有些類(lèi)似,它可以用來(lái)推導(dǎo)一個(gè)表達(dá)式的類(lèi)型,比如下面的例子:

int a = 0b10'001'000;
cout << a << endl;
decltype(a) c = a + 1; //int
cout << c << endl;

decltype(3) b = 3; // int&&
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

需要解釋一下的是這個(gè)例子中 3 是個(gè)臨時(shí)變量。所以推導(dǎo)出 b 的類(lèi)型是一個(gè) int 型的右值引用。但是作為函數(shù)返回值時(shí),推導(dǎo)出的就不是右值引用了。

decltype(5) getFive() { return 5; } // int
  • 1
  • 2

C++ 11 中 auto 和 decltype 還可以配合使用,用來(lái)推導(dǎo)函數(shù)的返回值類(lèi)型。下面是個(gè)例子:

auto getValue(int x) -> decltype(x) { return x; } // int
  • 1
  • 2

這么寫(xiě)還是挺繁瑣的, C++ 14 中做了簡(jiǎn)化??梢院?jiǎn)單的寫(xiě)為:

auto getValue(int x) { return x; } // int
  • 1
  • 2

不過(guò)我感覺(jué)這兩種函數(shù)寫(xiě)法作用都不大,因?yàn)槲覀儧](méi)法在頭文件中把函數(shù)聲明寫(xiě)為:

auto getValue(int x);
  • 1
  • 2

因?yàn)闆](méi)有函數(shù)體,根本無(wú)法做類(lèi)型推導(dǎo)…

C++14 中還支持如下的寫(xiě)法:

decltype(auto) = 3; // int&&
decltype(auto) getRef(int& x) { return x; } // int&
  • 1
  • 2
  • 3

這些寫(xiě)法知道也就行了,用處不大。

Lambda 函數(shù)

Lambda 函數(shù)的概念最早應(yīng)該來(lái)源于 Lisp 語(yǔ)言,現(xiàn)在也被 C++ 11 吸收進(jìn)來(lái)了。
Lambda 函數(shù)使得我們可以像定義一個(gè)變量一樣定義一個(gè)函數(shù)。比如下面這樣:

auto sum = [](int x, int y) -> int {return x + y;};
cout << sum(2, 3);
  • 1
  • 2
  • 3

上面的函數(shù)還可以簡(jiǎn)寫(xiě)為:

auto sum = [](int x, int y) { return x + y; };
  • 1
  • 2

編譯器會(huì)自動(dòng)推導(dǎo)返回值的類(lèi)型。

到了 C++ 14 Lambda 函數(shù)更是支持了泛型。

auto sum = [](auto x, auto y) {return x + y;};  
cout << sum(2, 3) << endl;
cout << sum(2.2, 3.0) << endl;
cout << sum(2.2, 3) << endl;
  • 1
  • 2
  • 3
  • 4
  • 5

Lambda 函數(shù)也可以作為函數(shù)的參數(shù)傳遞給函數(shù)。下面是個(gè)例子:

#include <iostream>
#include <functional>
using namespace std;
void call(int arg, function<void(int)> func) 
{
    func(arg);
}
int main() 
{
    auto printSquare = [](int x) { cout << x*x; };
    call(2, printSquare); // "4"
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

上面的例子其實(shí)還說(shuō)明 Lambda 函數(shù)不是普通的函數(shù)。它是一種特殊類(lèi)型的對(duì)象。比如下面的 Lambda 函數(shù):

auto sum = [](int x, int y) {return x + y;};  
  • 1
  • 2

寫(xiě)完整了應(yīng)該是 :

function<int(int)> sum = [](int x, int y) {return x + y;};  
  • 1
  • 2

Lambda 函數(shù)還有一些高級(jí)用法。比如Lambda 函數(shù)中的 “[]” 是有作用的。用它可以將所在域的其他變量引入到函數(shù)中。比如下面的例子:

void call(function<void()> func) { func(); }
int main() 
{
    int i = 2;
    auto printSquare = [i]() { cout << i*i; };
    call(printSquare); // "4"
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

Lambda 函數(shù)中 [] 里按值傳進(jìn)去的參數(shù)是只讀的。所以下面的代碼是錯(cuò)的:

int a = 10;
int b = [a](int i) { a++; return a * i; } (5); // 50
  • 1
  • 2
  • 3

我們可以添加一個(gè) mutable 關(guān)鍵字使得 a 不是只讀,但是 a 值的改變是不會(huì)影響函數(shù)外面的。

int a = 10;
int b = [a](int i) mutable { a++; return a * i; } (5);
cout << b << endl; // 55
cout << a << endl; // 10
  • 1
  • 2
  • 3
  • 4
  • 5

Lambda 函數(shù)還可以是無(wú)名函數(shù),這時(shí)定義函數(shù)的同時(shí)也要調(diào)用這個(gè)函數(shù)。否則因?yàn)檫@個(gè)函數(shù)沒(méi)有名字,之后就沒(méi)有調(diào)用的機(jī)會(huì)了。下面這兩種寫(xiě)法結(jié)果是相同的。

cout << [](int i) { return i*i; } (101) << endl;

auto printSquare = [](int i) { return i*i; };
cout << printSquare(101) << endl;
  • 1
  • 2
  • 3
  • 4
  • 5

利用 “[]” 也可以把結(jié)果傳出來(lái)。下面這兩種方法結(jié)果也是相同的。

int a = [](int i) { return i * i; } (11);
cout << a << endl;

[&a] (int i){ a = i * i;}(12);
cout << a << endl;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

C++ 14 還支持一些新的特性,比如下面這樣:

int a = 1;
[&, b = 2]() { a += b; }();
cout << a; // "3"
  • 1
  • 2
  • 3
  • 4

關(guān)于 Lambda 函數(shù),知道這些也就差不多了。

第一篇先寫(xiě)這么多。下一篇寫(xiě)寫(xiě)關(guān)于類(lèi)和對(duì)象的一些新特性。

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶(hù)發(fā)布,不代表本站觀(guān)點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買(mǎi)等信息,謹(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)遵守用戶(hù) 評(píng)論公約

    類(lèi)似文章 更多