C++11新特性


C++11新特性非常的多,就一個簡單的特性如果要講解的很清楚並附上事例可能就需要寫很多(個人覺着文章太長不利於理解),本片只大概介紹部分特性,以后有機會再針對個別特性做深入解釋。以下只是個人在使用過程中覺着經常使用到的部分,現在做如下解釋,錯誤之處望指正

1、右值和move語義

    C++11 增加一個新的非常數引用(reference)類型,稱作右值引用(R-value reference),標記為T &&。右值引用所引用的臨時對象可以在該臨時對象被初始化之后做修改,這是為了允許 move 語義​,具體可以參見【原】C++ 11右值引用

    注:stl中的容器都支持move語義,因此返回局部變量的時候效率不在是問題

2、POD定義的修正(plain old data

    一個極簡的類型或結構符合以下定義:極簡的默認建構式。這可以使用默認建構式語法,例如SomeConstructor() = default;

(1).極簡的復制建構式,可使用默認語法(default syntax)

(2).極簡的賦值操作符,可使用默認語法(default syntax)

(3).極簡的解構式,不可以是虛擬的(virtual)

    一個標准布局(standard-layout)的類型或結構符合以下定義:

(1).對所有non-static成員有相同的訪問控制(public, private, protected)

(2).沒有虛函數

(3).沒有虛擬基類

(4).只有符合標准布局的基類

(5).沒有和第一個定義的non-static成員相同類型的基類

(6).若非沒有帶有non-static成員的基類,就是最底層(繼承最末位)的類型沒有non-static數據成員而且至多一個帶有non-static成員的基類。基本上,在該類型的繼承體系中只會有一個類型帶有non-static成員。

(7).只有非靜態的(non-static)數據成員,且這些成員也是符合標准布局的類型​

3、初始化列表

    在引入C++ 11之前,只有數組能使用初始化列表。在C++ 11中一下都是合法的:

    1  int a{5}; ​

    2  char c{'X'}; 

    3  int p[5] = {1, 2,3, 4, 5};

    4  vector vctTemp{1, 2, 3}; 

    5  CPerson person{10, "Mike"}; 

    6   int b = 5.3;                     // b賦值成5,發生了窄轉換 

    7   int d{5.3};                      // 會提示編譯錯誤,避免了窄轉換

    map m_map = {{"test",1},{"test2",2}};​//不需要構造鍵值對

    vector test()

     {       

        return{"1","2","3"};//列表初始化返回值

     } 

4、類型推導​​

    有被明確初始化的變量可以使用 auto 關鍵字,decltype 能夠被用來在編譯期決定一個表示式的類型

auto someStrangeCallableType = boost::bind(&SomeFunction, _2, _1, someObject);​

    someStrangeCallableType 的類型就是模板函數 boost::bind 對特定引數所回返的類型。作為編譯器語義分析責任的一部份,這個類型能夠簡單地被編譯器決定,但用戶要通過查看來判斷類型就不是那么容易的一件事了

int someInt;

decltype(someInt) otherIntegerVariable = 5;//變量類型為int

    decltype 所表示的類型可以和 auto 推導出來的不同​

const std::vector v(1);  auto a = v[0];// a 為 int 型別

decltype(v[0])b;   // b 為 const int& 型別,即 std::vector::operator[](size_type)const 的回返型別  

auto c = 0;         // c 為 int 型別

auto d = c;         // d 為 int 型別      

decltype(c) e;      // e 為 int 型別,c實際的型別   

decltype((c)) f = e; // f 為 int& 型別,因 為(c)是左值

decltype(0) g;      // g為int型別,因為0是右值​

5、Lambda函數與表示式

    當使用 C++ 標准程序庫算法函數諸如 sort 和 find,用戶經常希望能夠在算法函數調用的附近定義一個臨時的述部函數(又稱謂詞函數,predicate function)

    ​​​​​​​C++ 11中的Lambda表達式用於定義並創建匿名的函數對象,以簡化編程工作。Lambda的語法形式如下:

    [函數對象參數] (操作符重載函數參數) mutable或exception聲明 ->返回值類型 {函數體}。可以看到,Lambda主要分為五個部分:[函數對象參數]、(操作符重載函數參數)、mutable或exception聲明、->返回值類型、{函數體}。下面分別進行介紹。

(1)、[函數對象參數],標識一個Lambda的開始,這部分必須存在,不能省略。函數對象參數是傳遞給編譯器自動生成的函數對象類的構造函數的。函數 對象參數只能使用那些到定義Lambda為止時Lambda所在作用范圍內可見的局部變量(包括Lambda所在類的this)。函數對象參數有以下形 式:        

1、空。沒有使用任何函數對象參數。           

2、=。函數體內可以使用Lambda所在作用范圍內所有可見的局部變量(包括Lambda所在類的this),並且是值傳遞方式(相當於編譯器自動為我們按值傳遞了所有局部變量)。         

3、&。函數體內可以使用Lambda所在作用范圍內所有可見的局部變量(包括Lambda所在類的this),並且是引用傳遞方式(相當於編譯器自動為我們按引用傳遞了所有局部變量)。          

4、this。函數體內可以使用Lambda所在類中的成員變量。       

5、a。將a按值進行傳遞。按值進行傳遞時,函數體內不能修改傳遞進來的a的拷貝,因為默認情況下函數是const的。要修改傳遞進來的a的拷貝,可以添加mutable修飾符。       6、&a。將a按引用進行傳遞。         

7、a, &b。將a按值進行傳遞,b按引用進行傳遞。      

8、=,&a, &b。除a和b按引用進行傳遞外,其他參數都按值進行傳遞。            

9、&, a, b。除a和b按值進行傳遞外,其他參數都按引用進行傳遞。    

(2)、(操作符重載函數參數),標識重載的()操作符的參數,沒有參數時,這部分可以省略。參數可以通過按值(如:(a,b))和按引用(如:(&a,&b))兩種方式進行傳遞。       

(3)、mutable或exception聲明,這部分可以省略。按值傳遞函數對象參數時,加上mutable修飾符后,可以修改按值傳遞進來的拷貝 (注意是能修改拷貝,而不是值本身)。exception聲明用於指定函數拋出的異常,如拋出整數類型的異常,可以使用throw(int)。     

(4)、->返回值類型,標識函數返回值的類型,當返回值為void,或者函數體中只有一處return的地方(此時編譯器可以自動推斷出返回值類型)時,這部分可以省略。    

(5)、{函數體},標識函數的實現,這部分不能省略,但函數體可以為空。

    使用qt的時候,connect的槽函數支持lambda表達式

    for_each(vctTemp.begin(), vctTemp.end(), [&](int v)mutable{ cout << v+a << endl; a++; });​//以引用方式傳遞作用域內所有可見的局部變量(包括this)

6、強類型枚舉

    在標准C++中,枚舉類型不是類型安全的,C++03 唯一提供的安全機制是一個整數或一個枚舉型值不能隱式轉換到另一個枚舉別型.

enum class typeA{a1 = 1, a2};

a1 == 1;​語句會報錯

    枚舉的名稱全數暴露於一般范圍中,因此兩個不同的枚舉,不可以有相同的枚舉名​

enum A{a, b};enum B{a, c};//美劇中的a是非法的​

7、顯式類型轉換子(explicite) 防止參數的隱式轉換

8、靜態assertion
​​​​​    static_assert( 3.14 < GREEKPI && GREEKPI < 3.15, "GREEKPI is inaccurate!" ) ;參數1如果為false,則彈出參數2這個字符串

9、constexpr:constexpr可以說是對const變量的擴展,它只是約束const變量的右側的式子必須能在編譯時就能算出值

10、類型別名​

typedef int (addptr*)(int a,int b);​

C++11中可以這樣:using addptr = int (int,int);​

11、nullptr

    nullptr是C++ 11中新加的一個關鍵字,用於標識空指針。引入nullptr后,可以解決某些函數重載時的二義性問題

    如果存在方法void f(int)和方法void f(char *p),則調用f​(0)時,在C++ 98中編譯失敗,有二義性編譯器會不錯,但是在C++11中調用f(int),方法f(char *)調用方式:f(nullptr)。

12、默認或者禁用

    當我們定義了自己的帶參數的構造函數時,編譯器將不再生成默認的構造函數,如果此時想使用默認的構造函數,則必須顯式地聲明並定義不帶參數的構造函數。在C++ 11中,我們可以使用default關鍵字來表明我們希望使用默認的構造函數。類似的,當我們不想外部使用編譯器自動生成的構造函數或賦值函數時,我們一般需要將其聲明成protected或private的。在C++ 11中,我們可以使用delete關鍵字來表明我們不希望編譯器生成默認的構造函數或賦值函數

CPerson() = default; //CPerson的構造函數

CPerson(const CPerson &person) = delete;​//CPerson的拷貝構造函數

13、模板右邊雙括號

    在C++ 98中,vector> vctTemp是一個非法的表達式,模板的兩個右尖括號中間必須有空格,但C++11中該表達式合法

引用文章

   C++11(C++新標准)​​

   C++11新標准

 

如果您覺得文章不錯,不妨給個 打賞,寫作不易,感謝各位的支持。您的支持是我最大的動力,謝謝!!! 

 

  


很重要--轉載聲明

  1. 本站文章無特別說明,皆為原創,版權所有,轉載時請用鏈接的方式,給出原文出處。同時寫上原作者:朝十晚八 or Twowords
  2. 如要轉載,請原文轉載,如在轉載時修改本文,請事先告知,謝絕在轉載時通過修改本文達到有利於轉載者的目的。 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM