當(dāng)前位置:首頁(yè) > 公眾號(hào)精選 > 后端技術(shù)指南針
[導(dǎo)讀]c++程序員面試過(guò)程中基本上都會(huì)被問(wèn)到c++11新特性吧,你是怎么回答的呢? 本文基本上涵蓋了c++11的所有新特性,并有詳細(xì)代碼介紹其用法,對(duì)關(guān)鍵知識(shí)點(diǎn)做了深入分析,對(duì)重要的知識(shí)點(diǎn)我單獨(dú)寫(xiě)了相關(guān)文章并附上了相關(guān)鏈接,我整理了完備的c++新特性腦圖(由于圖

c++程序員面試過(guò)程中基本上都會(huì)被問(wèn)到c++11新特性吧,你是怎么回答的呢?

本文基本上涵蓋了c++11的所有新特性,并有詳細(xì)代碼介紹其用法,對(duì)關(guān)鍵知識(shí)點(diǎn)做了深入分析,對(duì)重要的知識(shí)點(diǎn)我單獨(dú)寫(xiě)了相關(guān)文章并附上了相關(guān)鏈接,我整理了完備的c++新特性腦圖(由于圖片太大,我沒(méi)有放在文章里,同學(xué)可以在后臺(tái)回復(fù)消息“新特性”,即可下載完整圖片)。

auto & decltype

關(guān)于C++11新特性,最先提到的肯定是類型推導(dǎo),C++11引入了auto和decltype關(guān)鍵字,使用他們可以在編譯期就推導(dǎo)出變量或者表達(dá)式的類型,方便開(kāi)發(fā)者編碼也簡(jiǎn)化了代碼。

  • auto:讓編譯器在編譯器就推導(dǎo)出變量的類型,可以通過(guò)=右邊的類型推導(dǎo)出變量的類型。

auto a = 10; // 10是int型,可以自動(dòng)推導(dǎo)出a是int

  • decltype:相對(duì)于auto用于推導(dǎo)變量類型,而decltype則用于推導(dǎo)表達(dá)式類型,這里只用于編譯器分析表達(dá)式的類型,表達(dá)式實(shí)際不會(huì)進(jìn)行運(yùn)算。

cont int &i = 1;int a = 2;decltype(i) b = 2; // b是const int&

關(guān)于auto和decltype的詳細(xì)介紹請(qǐng)看:一文吃透C++11中auto和decltype知識(shí)點(diǎn)

左值右值

眾所周知C++11新增了右值引用,這里涉及到很多概念:

  • 左值:可以取地址并且有名字的東西就是左值。

  • 右值:不能取地址的沒(méi)有名字的東西就是右值。

  • 純右值:運(yùn)算表達(dá)式產(chǎn)生的臨時(shí)變量、不和對(duì)象關(guān)聯(lián)的原始字面量、非引用返回的臨時(shí)變量、lambda表達(dá)式等都是純右值。

  • 將亡值:可以理解為即將要銷毀的值。

  • 左值引用:對(duì)左值進(jìn)行引用的類型。

  • 右值引用:對(duì)右值進(jìn)行引用的類型。

  • 移動(dòng)語(yǔ)義:轉(zhuǎn)移資源所有權(quán),類似于轉(zhuǎn)讓或者資源竊取的意思,對(duì)于那塊資源,轉(zhuǎn)為自己所擁有,別人不再擁有也不會(huì)再使用。

  • 完美轉(zhuǎn)發(fā):可以寫(xiě)一個(gè)接受任意實(shí)參的函數(shù)模板,并轉(zhuǎn)發(fā)到其它函數(shù),目標(biāo)函數(shù)會(huì)收到與轉(zhuǎn)發(fā)函數(shù)完全相同的實(shí)參。

  • 返回值優(yōu)化:當(dāng)函數(shù)需要返回一個(gè)對(duì)象實(shí)例時(shí)候,就會(huì)創(chuàng)建一個(gè)臨時(shí)對(duì)象并通過(guò)復(fù)制構(gòu)造函數(shù)將目標(biāo)對(duì)象復(fù)制到臨時(shí)對(duì)象,這里有復(fù)制構(gòu)造函數(shù)和析構(gòu)函數(shù)會(huì)被多余的調(diào)用到,有代價(jià),而通過(guò)返回值優(yōu)化,C++標(biāo)準(zhǔn)允許省略調(diào)用這些復(fù)制構(gòu)造函數(shù)。

這里的詳細(xì)介紹請(qǐng)看:左值引用、右值引用、移動(dòng)語(yǔ)義、完美轉(zhuǎn)發(fā),你知道的不知道的都在這里

列表初始化

在C++11中可以直接在變量名后面加上初始化列表來(lái)進(jìn)行對(duì)象的初始化,詳細(xì)介紹一定要看這篇文章:學(xué)會(huì)C++11列表初始化

std::function & std::bind & lambda表達(dá)式

c++11新增了std::function、std::bind、lambda表達(dá)式等封裝使函數(shù)調(diào)用更加方便,詳細(xì)介紹請(qǐng)看:搞定c++11新特性std::function和lambda表達(dá)式

模板的改進(jìn)

C++11關(guān)于模板有一些細(xì)節(jié)的改進(jìn):

  • 模板的右尖括號(hào)

  • 模板的別名

  • 函數(shù)模板的默認(rèn)模板參數(shù)

詳細(xì)介紹請(qǐng)看:C++11的模板改進(jìn)

并發(fā)

c++11關(guān)于并發(fā)引入了好多好東西,有:

  • std::thread相關(guān)

  • std::mutex相關(guān)

  • std::lock相關(guān)

  • std::atomic相關(guān)

  • std::call_once相關(guān)

  • volatile相關(guān)

  • std::condition_variable相關(guān)

  • std::future相關(guān)

  • async相關(guān)

詳細(xì)介紹請(qǐng)看:c++11新特性之線程相關(guān)所有知識(shí)點(diǎn)

這里也使用c++11來(lái)實(shí)現(xiàn)的線程池和定時(shí)器,可以看:

C++線程池的實(shí)現(xiàn)之格式修訂版

C++定時(shí)器的實(shí)現(xiàn)之格式修訂版

智能指針

很多人談到c++,說(shuō)它特別難,可能有一部分就是因?yàn)閏++的內(nèi)存管理吧,不像java那樣有虛擬機(jī)動(dòng)態(tài)的管理內(nèi)存,在程序運(yùn)行過(guò)程中可能就會(huì)出現(xiàn)內(nèi)存泄漏,然而這種問(wèn)題其實(shí)都可以通過(guò)c++11引入的智能指針來(lái)解決,相反我還認(rèn)為這種內(nèi)存管理還是c++語(yǔ)言的優(yōu)勢(shì),因?yàn)楸M在掌握。

c++11引入了三種智能指針:

  • std::shared_ptr

  • std::weak_ptr

  • std::unique_ptr

詳細(xì)介紹請(qǐng)看:c++11新特性之智能指針

基于范圍的for循環(huán)

直接看代碼

vector<int> vec;
for (auto iter = vec.begin(); iter != vec.end(); iter++) { // before c++11 cout << *iter << endl;}
for (int i : vec) { // c++11基于范圍的for循環(huán)cout << "i" << endl;}

委托構(gòu)造函數(shù)

委托構(gòu)造函數(shù)允許在同一個(gè)類中一個(gè)構(gòu)造函數(shù)調(diào)用另外一個(gè)構(gòu)造函數(shù),可以在變量初始化時(shí)簡(jiǎn)化操作,通過(guò)代碼來(lái)感受下委托構(gòu)造函數(shù)的妙處吧:

不使用委托構(gòu)造函數(shù):

struct A { A(){} A(int a) { a_ = a; }
A(int a, int b) { // 好麻煩 a_ = a; b_ = b; }
A(int a, int b, int c) { // 好麻煩 a_ = a; b_ = b; c_ = c; }
int a_; int b_; int c_;};

使用委托構(gòu)造函數(shù):

struct A { A(){} A(int a) { a_ = a; }
A(int a, int b) : A(a) { b_ = b; }
A(int a, int b, int c) : A(a, b) { c_ = c; }
int a_; int b_; int c_;};

初始化變量是不是方便了許多。

繼承構(gòu)造函數(shù)

繼承構(gòu)造函數(shù)可以讓派生類直接使用基類的構(gòu)造函數(shù),如果有一個(gè)派生類,我們希望派生類采用和基類一樣的構(gòu)造方式,可以直接使用基類的構(gòu)造函數(shù),而不是再重新寫(xiě)一遍構(gòu)造函數(shù),老規(guī)矩,看代碼:

不使用繼承構(gòu)造函數(shù):

struct Base { Base() {} Base(int a) { a_ = a; }
Base(int a, int b) : Base(a) { b_ = b; }
Base(int a, int b, int c) : Base(a, b) { c_ = c; }
int a_; int b_; int c_;};
struct Derived : Base { Derived() {} Derived(int a) : Base(a) {} // 好麻煩 Derived(int a, int b) : Base(a, b) {} // 好麻煩 Derived(int a, int b, int c) : Base(a, b, c) {} // 好麻煩};int main() { Derived a(1, 2, 3); return 0;}

使用繼承構(gòu)造函數(shù):

struct Base { Base() {} Base(int a) { a_ = a; }
Base(int a, int b) : Base(a) { b_ = b; }
Base(int a, int b, int c) : Base(a, b) { c_ = c; }
int a_; int b_; int c_;};
struct Derived : Base { using Base::Base;};
int main() { Derived a(1, 2, 3); return 0;}

只需要使用using Base::Base繼承構(gòu)造函數(shù),就免去了很多重寫(xiě)代碼的麻煩。

nullptr

nullptr是c++11用來(lái)表示空指針新引入的常量值,在c++中如果表示空指針語(yǔ)義時(shí)建議使用nullptr而不要使用NULL,因?yàn)镹ULL本質(zhì)上是個(gè)int型的0,其實(shí)不是個(gè)指針。舉例:

void func(void *ptr) { cout << "func ptr" << endl;}
void func(int i) { cout << "func i" << endl;}
int main() { func(NULL); // 編譯失敗,會(huì)產(chǎn)生二義性 func(nullptr); // 輸出func ptr return 0;}

final & override

c++11關(guān)于繼承新增了兩個(gè)關(guān)鍵字,final用于修飾一個(gè)類,表示禁止該類進(jìn)一步派生和虛函數(shù)的進(jìn)一步重載,override用于修飾派生類中的成員函數(shù),標(biāo)明該函數(shù)重寫(xiě)了基類函數(shù),如果一個(gè)函數(shù)聲明了override但父類卻沒(méi)有這個(gè)虛函數(shù),編譯報(bào)錯(cuò),使用override關(guān)鍵字可以避免開(kāi)發(fā)者在重寫(xiě)基類函數(shù)時(shí)無(wú)意產(chǎn)生的錯(cuò)誤。

示例代碼1:

struct Base { virtual void func() { cout << "base" << endl; }};
struct Derived : public Base{ void func() override { // 確保func被重寫(xiě) cout << "derived" << endl; }
void fu() override { // error,基類沒(méi)有fu(),不可以被重寫(xiě) }};

示例代碼2:

struct Base final { virtual void func() { cout << "base" << endl; }};
struct Derived : public Base{ // 編譯失敗,final修飾的類不可以被繼承 void func() override { cout << "derived" << endl; }
};

default

c++11引入default特性,多數(shù)時(shí)候用于聲明構(gòu)造函數(shù)為默認(rèn)構(gòu)造函數(shù),如果類中有了自定義的構(gòu)造函數(shù),編譯器就不會(huì)隱式生成默認(rèn)構(gòu)造函數(shù),如下代碼:

struct A { int a; A(int i) { a = i; }};
int main() { A a; // 編譯出錯(cuò) return 0;}

上面代碼編譯出錯(cuò),因?yàn)闆](méi)有匹配的構(gòu)造函數(shù),因?yàn)榫幾g器沒(méi)有生成默認(rèn)構(gòu)造函數(shù),而通過(guò)default,程序員只需在函數(shù)聲明后加上“=default;”,就可將該函數(shù)聲明為 defaulted 函數(shù),編譯器將為顯式聲明的 defaulted 函數(shù)自動(dòng)生成函數(shù)體,如下:

struct A { A() = default; int a; A(int i) { a = i; }};
int main() { A a; return 0;}

編譯通過(guò)。

delete

c++中,如果開(kāi)發(fā)人員沒(méi)有定義特殊成員函數(shù),那么編譯器在需要特殊成員函數(shù)時(shí)候會(huì)隱式自動(dòng)生成一個(gè)默認(rèn)的特殊成員函數(shù),例如拷貝構(gòu)造函數(shù)或者拷貝賦值操作符,如下代碼:

struct A { A() = default; int a; A(int i) { a = i; }};
int main() { A a1; A a2 = a1; // 正確,調(diào)用編譯器隱式生成的默認(rèn)拷貝構(gòu)造函數(shù) A a3; a3 = a1; // 正確,調(diào)用編譯器隱式生成的默認(rèn)拷貝賦值操作符}

而我們有時(shí)候想禁止對(duì)象的拷貝與賦值,可以使用delete修飾,如下:

struct A { A() = default; A(const A&) = delete; A& operator=(const A&) = delete; int a; A(int i) { a = i; }};
int main() { A a1; A a2 = a1; // 錯(cuò)誤,拷貝構(gòu)造函數(shù)被禁用 A a3; a3 = a1; // 錯(cuò)誤,拷貝賦值操作符被禁用}

delele函數(shù)在c++11中很常用,std::unique_ptr就是通過(guò)delete修飾來(lái)禁止對(duì)象的拷貝的。

explicit

explicit專用于修飾構(gòu)造函數(shù),表示只能顯式構(gòu)造,不可以被隱式轉(zhuǎn)換,根據(jù)代碼看explicit的作用:

不用explicit:

struct A { A(int value) { // 沒(méi)有explicit關(guān)鍵字 cout << "value" << endl; }};
int main() { A a = 1; // 可以隱式轉(zhuǎn)換 return 0;}

使用explicit:

struct A { explicit A(int value) { cout << "value" << endl; }};
int main() { A a = 1; // error,不可以隱式轉(zhuǎn)換 A aa(2); // ok return 0;}

const

因?yàn)橐v后面的constexpr,所以這里簡(jiǎn)單介紹下const。

const字面意思為只讀,可用于定義變量,表示變量是只讀的,不可以更改,如果更改,編譯期間就會(huì)報(bào)錯(cuò)。

主要用法如下:

  1. 用于定義常量,const的修飾的變量不可更改。

const int value = 5;
  1. 指針也可以使用const,這里有個(gè)小技巧,從右向左讀,即可知道const究竟修飾的是指針還是指針?biāo)赶虻膬?nèi)容。

char *const ptr; // 指針本身是常量const char* ptr; // 指針指向的變量為常量
  1. 在函數(shù)參數(shù)中使用const,一般會(huì)傳遞類對(duì)象時(shí)會(huì)傳遞一個(gè)const的引用或者指針,這樣可以避免對(duì)象的拷貝,也可以防止對(duì)象被修改。

class A{};void func(const A& a);
  1. const修飾類的成員變量,表示是成員常量,不能被修改,可以在初始化列表中被賦值。

class A {const int value = 5;};class B {const int value;B(int v) : value(v){}};
  1. 修飾類成員函數(shù),表示在該函數(shù)內(nèi)不可以修改該類的成員變量。

class A{void func() const;};
  1. 修飾類對(duì)象,類對(duì)象只能調(diào)用該對(duì)象的const成員函數(shù)。

class A {void func() const;};const A a;a.func();

constexpr

constexpr是c++11新引入的關(guān)鍵字,用于編譯時(shí)的常量和常量函數(shù),這里直接介紹constexpr和const的區(qū)別:

兩者都代表可讀,const只表示read only的語(yǔ)義,只保證了運(yùn)行時(shí)不可以被修改,但它修飾的仍然有可能是個(gè)動(dòng)態(tài)變量,而constexpr修飾的才是真正的常量,它會(huì)在編譯期間就會(huì)被計(jì)算出來(lái),整個(gè)運(yùn)行過(guò)程中都不可以被改變,constexpr可以用于修飾函數(shù),這個(gè)函數(shù)的返回值會(huì)盡可能在編譯期間被計(jì)算出來(lái)當(dāng)作一個(gè)常量,但是如果編譯期間此函數(shù)不能被計(jì)算出來(lái),那它就會(huì)當(dāng)作一個(gè)普通函數(shù)被處理。如下代碼:

#include<iostream>using namespace std;
constexpr int func(int i) { return i + 1;}
int main() { int i = 2; func(i);// 普通函數(shù) func(2);// 編譯期間就會(huì)被計(jì)算出來(lái)}

enum class

c++11新增有作用域的枚舉類型,看代碼

不帶作用域的枚舉代碼:

enum AColor { kRed, kGreen, kBlue};
enum BColor { kWhite, kBlack, kYellow};
int main() { if (kRed == kWhite) { cout << "red == white" << endl; } return 0;}

如上代碼,不帶作用域的枚舉類型可以自動(dòng)轉(zhuǎn)換成整形,且不同的枚舉可以相互比較,代碼中的紅色居然可以和白色比較,這都是潛在的難以調(diào)試的bug,而這種完全可以通過(guò)有作用域的枚舉來(lái)規(guī)避。

有作用域的枚舉代碼:

enum class AColor { kRed, kGreen, kBlue};
enum class BColor { kWhite, kBlack, kYellow};
int main() { if (AColor::kRed == BColor::kWhite) { // 編譯失敗 cout << "red == white" << endl; } return 0;}

使用帶有作用域的枚舉類型后,對(duì)不同的枚舉進(jìn)行比較會(huì)導(dǎo)致編譯失敗,消除潛在bug,同時(shí)帶作用域的枚舉類型可以選擇底層類型,默認(rèn)是int,可以改成char等別的類型。

enum class AColor : char { kRed, kGreen, kBlue};

我們平時(shí)編程過(guò)程中使用枚舉,一定要使用有作用域的枚舉取代傳統(tǒng)的枚舉。

非受限聯(lián)合體

c++11之前union中數(shù)據(jù)成員的類型不允許有非POD類型,而這個(gè)限制在c++11被取消,允許數(shù)據(jù)成員類型有非POD類型,看代碼:

struct A { int a; int *b;};
union U { A a; // 非POD類型 c++11之前不可以這樣定義聯(lián)合體 int b;};

對(duì)于什么是POD類型,大家可以自行查下資料,大體上可以理解為對(duì)象可以直接memcpy的類型。

sizeof

c++11中sizeof可以用的類的數(shù)據(jù)成員上,看代碼:

c++11前:

struct A { int data[10]; int a;};
int main() { A a; cout << "size " << sizeof(a.data) << endl; return 0;}

c++11后:

struct A { int data[10]; int a;};
int main() { cout << "size " << sizeof(A::data) << endl; return 0;}

想知道類中數(shù)據(jù)成員的大小在c++11中是不是方便了許多,而不需要定義一個(gè)對(duì)象,在計(jì)算對(duì)象的成員大小。

assertion

static_assert(true/false, message);

c++11引入static_assert聲明,用于在編譯期間檢查,如果第一個(gè)參數(shù)值為false,則打印message,編譯失敗。

自定義字面量

c++11可以自定義字面量,我們平時(shí)c++中都或多或少使用過(guò)chrono中的時(shí)間,例如:

std::this_thread::sleep_for(std::chrono::milliseconds(100)); // 100msstd::this_thread::sleep_for(std::chrono::seconds(100)); // 100s

其實(shí)沒(méi)必要這么麻煩,也可以這么寫(xiě):

std::this_thread::sleep_for(100ms); // c++14里可以這么使用,這里只是舉個(gè)自定義字面量使用的例子std::this_thread::sleep_for(100s);

這就是自定義字面量的使用,示例如下:

struct mytype { unsigned long long value;};constexpr mytype operator"" _mytype ( unsigned long long n ) { return mytype{n};}mytype mm = 123_mytype;cout << mm.value << endl;

關(guān)于自定義字面量,可以看下chrono的源代碼,相信大家會(huì)有很大收獲,需要源碼分析chrono的話,可以留言給我。

內(nèi)存對(duì)齊

什么是內(nèi)存對(duì)齊

理論上計(jì)算機(jī)對(duì)于任何變量的訪問(wèn)都可以從任意位置開(kāi)始,然而實(shí)際上系統(tǒng)會(huì)對(duì)這些變量的存放地址有限制,通常將變量首地址設(shè)為某個(gè)數(shù)N的倍數(shù),這就是內(nèi)存對(duì)齊。

為什么要內(nèi)存對(duì)齊
  1. 硬件平臺(tái)限制,內(nèi)存以字節(jié)為單位,不同硬件平臺(tái)不一定支持任何內(nèi)存地址的存取,一般可能以雙字節(jié)、4字節(jié)等為單位存取內(nèi)存,為了保證處理器正確存取數(shù)據(jù),需要進(jìn)行內(nèi)存對(duì)齊。

  2. 提高CPU內(nèi)存訪問(wèn)速度,一般處理器的內(nèi)存存取粒度都是N的整數(shù)倍,假如訪問(wèn)N大小的數(shù)據(jù),沒(méi)有進(jìn)行內(nèi)存對(duì)齊,有可能就需要兩次訪問(wèn)才可以讀取出數(shù)據(jù),而進(jìn)行內(nèi)存對(duì)齊可以一次性把數(shù)據(jù)全部讀取出來(lái),提高效率。

在c++11之前如果想創(chuàng)建內(nèi)存對(duì)齊需要:

void align_cpp11_before(){ static char data[sizeof(void *) + sizeof(A)]; const uintptr_t kAlign = sizeof(void *) - 1; char *align_ptr = reinterpret_cast<char *>(reinterpret_cast<uintptr_t>(data + kAlign) & ~kAlign); A *attr = new (align_ptr) A;}

c++11關(guān)于內(nèi)存對(duì)齊新增了一些函數(shù):

void align_cpp11_after(){ static std::aligned_storage<sizeof(A), alignof(A)>::type data; A *attr = new (&data) A;}

還有:alignof()、std::alignment_of()、alignas(),關(guān)于內(nèi)存對(duì)齊詳情可以看這篇文章:內(nèi)存對(duì)齊之格式修訂版

thread_local

c++11引入thread_local,用thread_local修飾的變量具有thread周期,每一個(gè)線程都擁有并只擁有一個(gè)該變量的獨(dú)立實(shí)例,一般用于需要保證線程安全的函數(shù)中。

#include <iostream>#include <thread>
class A { public: A() {} ~A() {}
void test(const std::string &name) { thread_local int count = 0; ++count; std::cout << name << ": " << count << std::endl; }};
void func(const std::string &name) { A a1; a1.test(name); a1.test(name); A a2; a2.test(name); a2.test(name);}
int main() { std::thread(func, "thread1").join(); std::thread(func, "thread2").join(); return 0;}

輸出:

thread1: 1thread1: 2thread1: 3thread1: 4thread2: 1thread2: 2thread2: 3thread2: 4

驗(yàn)證上述說(shuō)法,對(duì)于一個(gè)線程私有變量,一個(gè)線程擁有且只擁有一個(gè)該實(shí)例,類似于static。

基礎(chǔ)數(shù)值類型

c++11新增了幾種數(shù)據(jù)類型:long long、char16_t、char32_t等

隨機(jī)數(shù)功能

c++11關(guān)于隨機(jī)數(shù)功能則較之前豐富了很多,典型的可以選擇概率分布類型,先看如下代碼:

#include <time.h>
#include <iostream>#include <random>
using namespace std;
int main() { std::default_random_engine random(time(nullptr));
std::uniform_int_distribution<int> int_dis(0, 100); // 整數(shù)均勻分布 std::uniform_real_distribution<float> real_dis(0.0, 1.0); // 浮點(diǎn)數(shù)均勻分布
for (int i = 0; i < 10; ++i) { cout << int_dis(random) << ' '; } cout << endl;
for (int i = 0; i < 10; ++i) { cout << real_dis(random) << ' '; } cout << endl;
return 0;}

輸出:

38 100 93 7 66 0 68 99 41 70.232202 0.617716 0.959241 0.970859 0.230406 0.430682 0.477359 0.971858 0.0171148 0.64863

代碼中舉例的是整數(shù)均勻分布和浮點(diǎn)數(shù)均勻分布,c++11提供的概率分布類型還有好多,例如伯努利分布、正態(tài)分布等,具體可以見(jiàn)最后的參考資料。

正則表達(dá)式

c++11引入了regex庫(kù)更好的支持正則表達(dá)式,見(jiàn)代碼:

#include <iostream>#include <iterator>#include <regex>#include <string>
int main() { std::string s = "I know, I'll use2 regular expressions.";// 忽略大小寫(xiě) std::regex self_regex("REGULAR EXPRESSIONS", std::regex_constants::icase); if (std::regex_search(s, self_regex)) { std::cout << "Text contains the phrase 'regular expressions'\n"; }
std::regex word_regex("(\\w+)"); // 匹配字母數(shù)字等字符 auto words_begin = std::sregex_iterator(s.begin(), s.end(), word_regex); auto words_end = std::sregex_iterator();
std::cout << "Found " << std::distance(words_begin, words_end) << " words\n";
const int N = 6; std::cout << "Words longer than " << N << " characters:\n"; for (std::sregex_iterator i = words_begin; i != words_end; ++i) { std::smatch match = *i; std::string match_str = match.str(); if (match_str.size() > N) { std::cout << " " << match_str << '\n'; } }
std::regex long_word_regex("(\\w{7,})"); // 超過(guò)7個(gè)字符的單詞用[]包圍 std::string new_s = std::regex_replace(s, long_word_regex, "[$&]"); std::cout << new_s << '\n';}

chrono

c++11關(guān)于時(shí)間引入了chrono庫(kù),源于boost,功能強(qiáng)大,chrono主要有三個(gè)點(diǎn):

  • duration

  • time_point

  • clocks

duration

std::chrono::duration表示一段時(shí)間,常見(jiàn)的單位有s、ms等,示例代碼:

// 拿休眠一段時(shí)間舉例,這里表示休眠100msstd::this_thread::sleep_for(std::chrono::milliseconds(100));

sleep_for里面其實(shí)就是std::chrono::duration,表示一段時(shí)間,實(shí)際是這樣:

typedef duration<int64_t, milli> milliseconds;typedef duration<int64_t> seconds;

duration具體模板如下:

1 template <class Rep, class Period = ratio<1> > class duration;

Rep表示一種數(shù)值類型,用來(lái)表示Period的數(shù)量,比如int、float、double,Period是ratio類型,用來(lái)表示【用秒表示的時(shí)間單位】比如second,常用的duration<Rep, Period>已經(jīng)定義好了,在std::chrono::duration下:

  • ratio<3600, 1>:hours

  • ratio<60, 1>:minutes

  • ratio<1, 1>:seconds

  • ratio<1, 1000>:microseconds

  • ratio<1, 1000000>:microseconds

  • ratio<1, 1000000000>:nanosecons

ratio的具體模板如下:

template <intmax_t N, intmax_t D = 1> class ratio;

N代表分子,D代表分母,所以ratio表示一個(gè)分?jǐn)?shù),我們可以自定義Period,比如ratio<2, 1>表示單位時(shí)間是2秒。

time_point

表示一個(gè)具體時(shí)間點(diǎn),如2020年5月10日10點(diǎn)10分10秒,拿獲取當(dāng)前時(shí)間舉例:

std::chrono::time_point<std::chrono::high_resolution_clock> Now() { return std::chrono::high_resolution_clock::now();}// std::chrono::high_resolution_clock為高精度時(shí)鐘,下面會(huì)提到

clocks

時(shí)鐘,chrono里面提供了三種時(shí)鐘:

  • steady_clock

  • system_clock

  • high_resolution_clock

steady_clock

穩(wěn)定的時(shí)間間隔,表示相對(duì)時(shí)間,相對(duì)于系統(tǒng)開(kāi)機(jī)啟動(dòng)的時(shí)間,無(wú)論系統(tǒng)時(shí)間如何被更改,后一次調(diào)用now()肯定比前一次調(diào)用now()的數(shù)值大,可用于計(jì)時(shí)。

system_clock

表示當(dāng)前的系統(tǒng)時(shí)鐘,可以用于獲取當(dāng)前時(shí)間:

int main() { using std::chrono::system_clock; system_clock::time_point today = system_clock::now();
std::time_t tt = system_clock::to_time_t(today); std::cout << "today is: " << ctime(&tt);
return 0;}// today is: Sun May 10 09:48:36 2020

high_resolution_clock

high_resolution_clock表示系統(tǒng)可用的最高精度的時(shí)鐘,實(shí)際上就是system_clock或者steady_clock其中一種的定義,官方?jīng)]有說(shuō)明具體是哪個(gè),不同系統(tǒng)可能不一樣,我之前看gcc chrono源碼中high_resolution_clock是steady_clock的typedef。

更多關(guān)于chrono的介紹可以看下我之前的文章:RAII妙用之計(jì)算函數(shù)耗時(shí)

新增數(shù)據(jù)結(jié)構(gòu)

  • std::forward_list:?jiǎn)蜗蜴湵?,只可以前進(jìn),在特定場(chǎng)景下使用,相比于std::list節(jié)省了內(nèi)存,提高了性能

std::forward_list<int> fl = {1, 2, 3, 4, 5};for (const auto &elem : fl) { cout << elem;}
  • std::unordered_set:基于hash表實(shí)現(xiàn)的set,內(nèi)部不會(huì)排序,使用方法和set類似

  • std::unordered_map:基于hash表實(shí)現(xiàn)的map,內(nèi)部不會(huì)排序,使用方法和set類似

  • std::array:數(shù)組,在越界訪問(wèn)時(shí)拋出異常,建議使用std::array替代普通的數(shù)組

  • std::tuple:元組類型,類似pair,但比pair擴(kuò)展性好

typedef std::tuple<int, double, int, double> Mytuple;Mytuple t(0, 1, 2, 3);std::cout << "0 " << std::get<0>(t);std::cout << "1 " << std::get<1>(t);std::cout << "2 " << std::get<2>(t);std::cout << "3 " << std::get<3>(t);

新增算法

  • all_of:檢測(cè)表達(dá)式是否對(duì)范圍[first, last)中所有元素都返回true,如果都滿足,則返回true

std::vector<int> v(10, 2);if (std::all_of(v.cbegin(), v.cend(), [](int i) { return i % 2 == 0; })) {std::cout << "All numbers are even\n";}
  • any_of:檢測(cè)表達(dá)式是否對(duì)范圍[first, last)中至少一個(gè)元素返回true,如果滿足,則返回true,否則返回false,用法和上面一樣

  • none_of:檢測(cè)表達(dá)式是否對(duì)范圍[first, last)中所有元素都不返回true,如果都不滿足,則返回true,否則返回false,用法和上面一樣

  • find_if_not:找到第一個(gè)不符合要求的元素迭代器,和find_if相反

  • copy_if:復(fù)制滿足條件的元素

  • itoa:對(duì)容器內(nèi)的元素按序遞增

std::vector<int> l(10);std::iota(l.begin(), l.end(), 19); // 19為初始值for (auto n : l) std::cout << n << ' ';// 19 20 21 22 23 24 25 26 27 28
  • minmax_element:返回容器內(nèi)最大元素和最小元素位置

int main() { std::vector<int> v = {3, 9, 1, 4, 2, 5, 9};
auto result = std::minmax_element(v.begin(), v.end()); std::cout << "min element at: " << *(result.first) << '\n'; std::cout << "max element at: " << *(result.second) << '\n'; return 0;}// min element at: 1// max element at: 9
  • is_sorted、is_sorted_until:返回容器內(nèi)元素是否已經(jīng)排好序。

關(guān)于c++11的新特性基本上就是這些,相信各位看完一定會(huì)有所收獲。

參考資料

https://zh.cppreference.com/w/cpp/language/range-for
https://juejin.im/post/5dcaa857e51d457f7675360b
https://zhuanlan.zhihu.com/p/21930436
https://zh.wikipedia.org/wiki/Nullptr
https://zh.wikipedia.org/wiki/Constexpr
https://zh.cppreference.com/w/cpp/language/enum
https://kheresy.wordpress.com/2019/03/27/using-enum-class/
https://zh.cppreference.com/w/cpp/language/union
http://c.biancheng.net/view/7165.html
https://zhuanlan.zhihu.com/p/77585472
http://www.cplusplus.com/reference/random/
https://zh.cppreference.com/w/cpp/regex
https://www.cnblogs.com/jwk000/p/3560086.html
https://zh.cppreference.com/w/cpp/algorithm/all_any_none_of

REVIEW



往期回顧

一文讓你搞懂設(shè)計(jì)模式
RAII妙用之計(jì)算函數(shù)耗時(shí)
深入淺出虛擬內(nèi)存
C++線程池的實(shí)現(xiàn)之格式修訂版

大家有問(wèn)題可以點(diǎn)此留言 ,我會(huì)盡快回復(fù)~

免責(zé)聲明:本文內(nèi)容由21ic獲得授權(quán)后發(fā)布,版權(quán)歸原作者所有,本平臺(tái)僅提供信息存儲(chǔ)服務(wù)。文章僅代表作者個(gè)人觀點(diǎn),不代表本平臺(tái)立場(chǎng),如有問(wèn)題,請(qǐng)聯(lián)系我們,謝謝!

本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實(shí)性等。需要轉(zhuǎn)載請(qǐng)聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請(qǐng)及時(shí)聯(lián)系本站刪除。
換一批
延伸閱讀

9月2日消息,不造車的華為或?qū)⒋呱龈蟮莫?dú)角獸公司,隨著阿維塔和賽力斯的入局,華為引望愈發(fā)顯得引人矚目。

關(guān)鍵字: 阿維塔 塞力斯 華為

倫敦2024年8月29日 /美通社/ -- 英國(guó)汽車技術(shù)公司SODA.Auto推出其旗艦產(chǎn)品SODA V,這是全球首款涵蓋汽車工程師從創(chuàng)意到認(rèn)證的所有需求的工具,可用于創(chuàng)建軟件定義汽車。 SODA V工具的開(kāi)發(fā)耗時(shí)1.5...

關(guān)鍵字: 汽車 人工智能 智能驅(qū)動(dòng) BSP

北京2024年8月28日 /美通社/ -- 越來(lái)越多用戶希望企業(yè)業(yè)務(wù)能7×24不間斷運(yùn)行,同時(shí)企業(yè)卻面臨越來(lái)越多業(yè)務(wù)中斷的風(fēng)險(xiǎn),如企業(yè)系統(tǒng)復(fù)雜性的增加,頻繁的功能更新和發(fā)布等。如何確保業(yè)務(wù)連續(xù)性,提升韌性,成...

關(guān)鍵字: 亞馬遜 解密 控制平面 BSP

8月30日消息,據(jù)媒體報(bào)道,騰訊和網(wǎng)易近期正在縮減他們對(duì)日本游戲市場(chǎng)的投資。

關(guān)鍵字: 騰訊 編碼器 CPU

8月28日消息,今天上午,2024中國(guó)國(guó)際大數(shù)據(jù)產(chǎn)業(yè)博覽會(huì)開(kāi)幕式在貴陽(yáng)舉行,華為董事、質(zhì)量流程IT總裁陶景文發(fā)表了演講。

關(guān)鍵字: 華為 12nm EDA 半導(dǎo)體

8月28日消息,在2024中國(guó)國(guó)際大數(shù)據(jù)產(chǎn)業(yè)博覽會(huì)上,華為常務(wù)董事、華為云CEO張平安發(fā)表演講稱,數(shù)字世界的話語(yǔ)權(quán)最終是由生態(tài)的繁榮決定的。

關(guān)鍵字: 華為 12nm 手機(jī) 衛(wèi)星通信

要點(diǎn): 有效應(yīng)對(duì)環(huán)境變化,經(jīng)營(yíng)業(yè)績(jī)穩(wěn)中有升 落實(shí)提質(zhì)增效舉措,毛利潤(rùn)率延續(xù)升勢(shì) 戰(zhàn)略布局成效顯著,戰(zhàn)新業(yè)務(wù)引領(lǐng)增長(zhǎng) 以科技創(chuàng)新為引領(lǐng),提升企業(yè)核心競(jìng)爭(zhēng)力 堅(jiān)持高質(zhì)量發(fā)展策略,塑強(qiáng)核心競(jìng)爭(zhēng)優(yōu)勢(shì)...

關(guān)鍵字: 通信 BSP 電信運(yùn)營(yíng)商 數(shù)字經(jīng)濟(jì)

北京2024年8月27日 /美通社/ -- 8月21日,由中央廣播電視總臺(tái)與中國(guó)電影電視技術(shù)學(xué)會(huì)聯(lián)合牽頭組建的NVI技術(shù)創(chuàng)新聯(lián)盟在BIRTV2024超高清全產(chǎn)業(yè)鏈發(fā)展研討會(huì)上宣布正式成立。 活動(dòng)現(xiàn)場(chǎng) NVI技術(shù)創(chuàng)新聯(lián)...

關(guān)鍵字: VI 傳輸協(xié)議 音頻 BSP

北京2024年8月27日 /美通社/ -- 在8月23日舉辦的2024年長(zhǎng)三角生態(tài)綠色一體化發(fā)展示范區(qū)聯(lián)合招商會(huì)上,軟通動(dòng)力信息技術(shù)(集團(tuán))股份有限公司(以下簡(jiǎn)稱"軟通動(dòng)力")與長(zhǎng)三角投資(上海)有限...

關(guān)鍵字: BSP 信息技術(shù)
關(guān)閉
關(guān)閉