C++11的新特征簡略匯總引見 (二)。本站提示廣大學習愛好者:(C++11的新特征簡略匯總引見 (二))文章只能為提供參考,不一定能成為您想要的結果。以下是C++11的新特征簡略匯總引見 (二)正文
1. 規模for語句
C++11 引入了一種更加簡略的for語句,這類for語句可以很便利的遍歷容器或其他序列的一切元素
vector<int> vec = {1,2,3,4,5,6}; for(int x: vec) { cout<<x<<endl; }
2. 尾置前往類型
要想引入尾置類型,我們還得從龐雜的類型聲明說起。假如我們須要界說一個含有10個int元素的數組,普通是如許的:
int arr[10] = {0};
假如要界說指向這個數組的指針呢:
int (*p_arr)[10] = &arr; //留意:int *p_arr[10] 表現一個數組,有10個元素,元素類型是int*
假如要界說一個函數,這個函數接收一個char類型的參數,並前往一個指向10個int類型數組的指針呢:
int (*func(char x))[10];
如許的聲明是否是看的頭都年夜了,其實我們可以簡化一點,普通情形下我們可使用別號停止簡化,好比:
typedef int ARR[10] ; // 界說一個類型 ARR這是一個數組類型,含有10個int類型的元素
using ARR = int[10] ; // 同上
再界說如上的函數:
ARR * func(char x) ; // 函數前往的類型是 ARR* 也就是指向具有10個int元素數組的指針
固然在C++11中我們可以用之前講到過的別的一個症結字decltype:
decltype(arr) * func(char x) ; // decltype(arr)表達式會取得arr的類型
最初就輪到我們本節要說的C++11的別的一個特征,尾置前往類型,任何函數都可使用尾置前往類型,這類情勢關於前往類型比擬龐雜的函數最有用,好比下面的函數可使用以下方法:
auto func(char x) -> int(*) [10];
這類情勢將函數的前往類型寫在函數聲明的最初面,而且在函數形參列表前面加上 -> 符號,然後緊接著是函數須要前往的類型,因為函數的前往類型被放在了形參列表以後,所以在函數名後面應用一個 auto替換。
3. =default 生成默許結構函數
在C++的類中,假如我們沒有界說結構函數,編譯器會為我們分解默許的無參結構函數,假如我們界說了結構函數,則編譯器就不生成默許結構函數了,然則假如我們界說結構函數同時也願望編譯器生成默許結構函數呢? C++11中可以經由過程在結構函數的聲明中直接 =default的方法請求編譯器生成結構函數。
class ClassName{ public: ClassName(int x); ClassName()=default; // 顯示請求編譯器生成結構函數 };
4. 類對象成員的類內初始化
class ClassName { public: int x = 10; //C++11 之前是不許可的 };
5. lambda表達式與bind函數
lambda表達式是一個可以被挪用的代碼單位,相當於一個內聯函數,有參數和前往值和函數體。然則跟函數分歧的是,lambda表達式可以界說在函數的外部,一個完全的lambda表達式具有以下情勢:
[捕捉列表](參數列表) mutable -> 前往類型 {函數體}
int x = 10; int y = 20; auto f = [x,&y](int a ,int b){++y;return a+b+x+y;}; cout<<f(1,2)<<endl; //34 cout<<y<<endl; //21
lambda可以省略參數列表(假如沒有參數的話),可以省略前往類型,然則不克不及省略捕捉部門與函數體部門,即便捕捉列表為空,也要有一個空的[],lambda有兩種捕捉,一種是值捕捉,一種是援用捕捉。假如是值捕捉那末lambda中取得的是捕捉的變量的正本,假如是援用捕捉則取得的是援用,可以在lambda外部修正援用的變量的值,如上x是值捕捉,y是援用捕捉,lambda中默許是值捕捉,假如變量後面添加&則是援用捕捉,別的lambda中還有兩種情勢的援用捕捉,例如[=]表現值捕捉一切可見的變量,而[&]則表現援用捕捉一切可見變量。假如願望值捕捉一切可見變量,然則又有個體變量采取援用捕捉呢,[=,&x]表現值捕捉一切可見變量,同時援用捕捉x。而[&,x]則表現援用捕捉一切可見變量,x采取值捕捉的方法。
有關bind函數,在許多處所我們可使用函數調換lambda表達式,究竟假如許多處所須要用到統一個lambda表達式,並且這個lambda表達式比擬長的話,將其界說成函數應當是最好的。關於沒有捕捉列表的lambda表達式我們可以直接應用函數替換,例如:
void main() { auto f=[](int x,int y){return x+y}; f(); }
我們可以用上面的方法替換:
int f(int x,int y) { return x+y; } void main() { f(); }
與下面的lambda是等價的,然則關於有捕捉列表的lambda表達式應當怎樣處置呢,例如:
void main() { int x = 10; int y = 20; auto f = [x,&y](int a ,int b){return a+b+x+y;}; //一個值捕捉,一個援用捕捉 f(33,44); }
假如轉換成函數的情勢:
int x = 10; int y = 20; int f(int a,int b) { return a+bx+y; } void main() { f(33,44); }
這是一種可行的辦法,然則總不克不及把一切的捕捉變量界說玉成局變量吧。如今的症結成績是lambda的捕捉表達式中的內容轉換成函數弗成行,C++11供給了bind函數來完成如許的操作。
#include <functional> //bind() #include <iostream> using namespace std; using namespace std::placeholders; // _1,_2地點的定名空間 int f(int x,int y,int a,int b) { return a+b+x+y; } void main() { int x = 10; int y = 20; auto f_wrap = bind(f,x,y,_1,_2); cout<<f_wrap(33,44)<<endl; // _1,_2是占位符,表現挪用f_wrap的時刻_1是第一個參數,_2是第二個參數。終究會被調換成挪用 f(10,20,33,44) }
假如援用類型的捕捉怎樣做呢,看上面的例子,用lambda是如許的:
#include <iostream> #include <functional> using namespace std; using namespace std::placeholders; void main() { int x = 10; ostream &o = cout; auto f =[&o](int a){o<<a<<endl;}; // 留意這裡的輸入對象是用的援用捕捉 f(x); }
應用bind是如許的:
#include <iostream> #include <functional> using namespace std; using namespace std::placeholders; void f(ostream &o,int x) { o<<x<<endl; } int main() { int x = 10; auto f_wrap = bind(f,ref(cout),_1); //將變量的援用傳遞到bind中是個成績,為此C++11供給了ref()函數用於取得援用 f_wrap(x); return 0 ; }
6. 智能指針share_ptr,unique_ptr
C++11中引入了幾種智能指針,智能指針可以或許主動釋放所指向的對象,個中shared_ptr許可多個指針指向統一個對象,unique_ptr則獨有所指向的對象,我們重要解釋shared_ptr的應用。經由過程應用make_shared<type>()函數發生智能指針對象。
shared_ptr<int> p = make_shared<int>(40); // p指向一個值為40的int對象
shared_ptr<string> p2 = make_shared<string>(10,'c'); //指向值為'cccccccccc'的string對象
make_shared<type>()函數中傳遞的值要與對應的type的結構函數相婚配,現實上應當就是直接挪用的對應type的結構函數。
我們可使用new初始化的指針來初始化智能指針:
share_ptr<int> p (new int(40));
p.get(); // 應用share_ptr<type>的get()函數來取得其聯系關系的原始指針。
shared_ptr對象在分開其感化域(例如一個函數體),會主動釋放其聯系關系的指針指向的靜態內存,就像部分變量那樣。別的多個shared_ptr可以指向一個對象,當最初一個shared_ptr對象燒毀的時刻才會燒毀其聯系關系的誰人對象的靜態內存。這裡應用了援用記數。
7. 右值援用與move挪用,挪動結構函數
為了支撐挪動操作,C++11中應用了一種稱為右值援用的類型。挪動操作是甚麼呢,普通情形下我們將一個對象賦值給另外一個對象的時刻會挪用對象到拷貝結構函數或許拷貝賦值運算符。而挪動結構函數和挪動賦值運算符則用來將數據從一個對象挪動到另外一個對象。在許多情形下對象拷貝以後須要被燒毀,此時應用挪動操作會年夜幅進步機能。右值援用被應用以後,其聯系關系的對象會被燒毀。右值援用應用兩個&&表現,例如 int && 表現右值援用,而int &則是左值。經由過程C++11尺度庫供給的函數 std::move()可以獲得某一對象的右值援用。
TestClass::TestClass(TestClass &&t) noexcept //挪動結構函數不該該拋出任何異常
:x(t.x),y(t.y),z(t.z),p(t.p)
{
t.p=nullptr; // 完成挪動操作以後須要包管被挪動的對象的析構是平安的,所以源對象的指針成員置為空,隨後t的析構函數將會被主動挪用,t被燒毀。
}
8. function
C++11中供給了名為function的尺度庫類型,界說在頭文件<functional>中,該類型用來存儲一個可挪用的對象,同一了一切可以像函數一樣挪用的挪用情勢,例如:
#include <functional> #include <iostream> using namespace std; int add(int x,int y) { return x+y; } class Add { public: int operator()(int x,int y) { return x+y; } }; void main() { //function模版的參數是函數挪用情勢,包含前往類型,和參數列表個數和類型 function<int(int,int)> f1 = add; //函數指針 function<int(int,int)> f2 = Add(); // 可挪用類對象 function<int(int,int)> f3 = [](int x,int y){return x+y;}; //lambda表達式 cout<<f1(10,20)<<" "<<f2(30,40)<<" "<<f3(50,60)<<endl; }
9. 其他新增類型(array,forward_list,bitset,regex)
現實上C++11中除一些語法特征新增以外,還增長了一些新的庫。例如array相當於我們傳統應用的定長數組,支撐隨機拜訪,不克不及添加刪除元素,弗成以像vector一樣增加,應用array比傳統數組加倍平安。
forward_list是C++11中增長的單向鏈表
regex則是C++11中新增的正則表達式庫
10. 總結
C++11中增長了一些庫,庫自己的應用不做過量引見,可以參考C++尺度庫/STL源碼分析,這都是用零丁的年夜部頭書本講授的,有些特征和庫是我感到比擬冷艷的,例如: