【C++11】30分鐘瞭解C++11新特性


點擊進入個人新博客html


###什麼是C++11java

C++11是曾經被叫作C++0x,是對目前C++語言的擴展和修正,C++11不只包含核心語言的新機能,並且擴展了C++的標準程序庫**(STL),併入了大部分的C++ Technical Report 1(TR1)**程序庫(數學的特殊函數除外)。編程

C++11包括大量的新特性:包括lambda表達式,類型推導關鍵字auto、decltype,和模板的大量改進。數組

本文將對C++11的以上新特性進行簡單的講解,以便你們可以快速瞭解到C++11對C++的易用性方面祈禱的巨大做用。閉包

若是您以爲本文的排版不是很舒服,能夠查看個人PDF文檔:百度盤連接less

###新的關鍵字函數

####autovisual-studio

C++11中引入auto第一種做用是爲了自動類型推導指針

auto的自動類型推導,用於從初始化表達式中推斷出變量的數據類型。經過auto的自動類型推導,能夠大大簡化咱們的編程工做code

auto實際上實在編譯時對變量進行了類型推導,因此不會對程序的運行效率形成不良影響

另外,彷佛auto並不會影響編譯速度,由於編譯時原本也要右側推導而後判斷與左側是否匹配。

<!-- lang: cpp -->
auto a; // 錯誤,auto是經過初始化表達式進行類型推導,若是沒有初始化表達式,就沒法肯定a的類型
auto i = 1;
auto d = 1.0;
auto str = "Hello World";
auto ch = 'A';
auto func = less<int>();
vector<int> iv;
auto ite = iv.begin();
auto p = new foo() // 對自定義類型進行類型推導

auto不光有以上的應用,它在模板中也是大顯身手,好比下例這個加工產品的例子中,若是不使用auto就必須聲明Product這一模板參數:

template <typename Product, typename Creator>
void processProduct(const Creator& creator) {
    Product* val = creator.makeObject();
    // do somthing with val
}		
		.

若是使用auto,則能夠這樣寫:

template <typename Creator>
void processProduct(const Creator& creator) {
    auto val = creator.makeObject();
    // do somthing with val
}

拋棄了麻煩的模板參數,整個代碼變得更加正解了。

####decltype

decltype實際上有點像auto的反函數,auto可讓你聲明一個變量,而decltype則能夠從一個變量或表達式中獲得類型,有實例以下:

int x = 3;
decltype(x) y = x;

有人會問,decltype的實用之處在哪裏呢,咱們接着上邊的例子繼續說下去,若是上文中的加工產品的例子中咱們想把產品做爲返回值該怎麼辦呢?咱們能夠這樣寫:

template <typename Creator>
auto processProduct(const Creator& creator) -> decltype(creator.makeObject()) {
    auto val = creator.makeObject();
    // do somthing with val
}

####nullptr

nullptr是爲了解決原來C++中NULL的二義性問題而引進的一種新的類型,由於NULL實際上表明的是0,

void F(int a){
    cout<<a<<endl;
}

void F(int *p){
    assert(p != NULL);
    
    cout<< p <<endl;
}

int main(){
    
    int *p = nullptr;
    int *q = NULL;
    bool equal = ( p == q ); // equal的值爲true,說明p和q都是空指針
    int a = nullptr; // 編譯失敗,nullptr不能轉型爲int
    F(0); // 在C++98中編譯失敗,有二義性;在C++11中調用F(int)
    F(nullptr);

    return 0;
}

###序列for循環

在C++中for循環可使用相似java的簡化的for循環,能夠用於遍歷數組,容器,string以及由begin和end函數定義的序列(即有Iterator),示例代碼以下:

map<string, int> m{{"a", 1}, {"b", 2}, {"c", 3}};
for (auto p : m){
    cout<<p.first<<" : "<<p.second<<endl;
}

###Lambda表達式

lambda表達式相似Javascript中的閉包,它能夠用於建立並定義匿名的函數對象,以簡化編程工做。Lambda的語法以下:

[函數對象參數](操做符重載函數參數)->返回值類型{函數體}

vector<int> iv{5, 4, 3, 2, 1};
int a = 2, b = 1;

for_each(iv.begin(), iv.end(), [b](int &x){cout<<(x + b)<<endl;}); // (1)

for_each(iv.begin(), iv.end(), [=](int &x){x *= (a + b);});		// (2)

for_each(iv.begin(), iv.end(), [=](int &x)->int{return x * (a + b);});// (3)
  • []內的參數指的是Lambda表達式能夠取得的全局變量。(1)函數中的b就是指函數能夠獲得在Lambda表達式外的全局變量,若是在[]中傳入=的話,便是能夠取得全部的外部變量,如(2)和(3)Lambda表達式
  • ()內的參數是每次調用函數時傳入的參數
  • ->後加上的是Lambda表達式返回值的類型,如(3)中返回了一個int類型的變量

###變長參數的模板

咱們在C++中都用過pair,pair可使用make_pair構造,構造一個包含兩種不一樣類型的數據的容器。好比,以下代碼:

auto p = make_pair(1, "C++ 11");

因爲在C++11中引入了變長參數模板,因此發明了新的數據類型:tuple,tuple是一個N元組,能夠傳入1個, 2個甚至多個不一樣類型的數據

auto t1 = make_tuple(1, 2.0, "C++ 11");
auto t2 = make_tuple(1, 2.0, "C++ 11", {1, 0, 2});

這樣就避免了從前的pair中嵌套pair的醜陋作法,使得代碼更加整潔

另外一個常常見到的例子是Print函數,在C語言中printf能夠傳入多個參數,在C++11中,咱們能夠用變長參數模板實現更簡潔的Print

template<typename head, typename... tail>
void Print(Head head, typename... tail) {
	cout<< head <<endl;
	Print(tail...);
}

Print中能夠傳入多個不一樣種類的參數,以下:

Print(1, 1.0, "C++11");

###更加優雅的初始化方法

在引入C++11以前,只有數組能使用初始化列表,其餘容器想要使用初始化列表,只能用如下方法:

int arr[3] = {1, 2, 3}
vector<int> v(arr, arr + 3);

在C++11中,咱們可使用如下語法來進行替換:

int arr[3]{1, 2, 3};
vector<int> iv{1, 2, 3};
map<int, string>{{1, "a"}, {2, "b"}};
string str{"Hello World"};

###而後呢...

若是你想了解更多C++11使人興奮的新特性,我會向你推薦這兩個博客:

胡健的C++11系列博文

ToWrting的C++11系列博文

C++11的編譯器支持列表

相關文章
相關標籤/搜索