自從Cocos2d-x3.0開始,Cocos2dx就正式的使用了C++11標準.C++11簡潔方便的特性使程序的可拓展性和可維護性大大提升,也提升了代碼的書寫速度。html
下面咱們就來一塊兒學習一下Cocos2d-x開發中那些不得不瞭解的C++11知識。編程
1.初始化列表數組
POD結構或者數組根據成員在結構內定義的順序,可使用初始化列表來進行初始化以簡化代碼。閉包
struct StructA{ int a; int b; }; StructA sa={1,2};
在C++03中,非POD結構的類或者STL容器並不支持這種簡便的寫法,而C++11提供了強大的支持。使用std::initializer_list可讓類和普通函數使用初始化列表,而且STL容器也是可使用初始化列表,代碼以下:ide
//類使用初始化列表 class ClassA{ public: ClassA(std::initializer_list<int>list){} }; ClassA a = { 1, 2, 3 }; /*注意!使用std::initializer_list須要先include <initializer_list>頭文件*/
//函數使用初始化列表 void func(std::initializer_list<float>list){ /*Function Body*/ } func({1.6f,2.8f});
/*注意!使用std::initializer_list須要先include <initializer_list>頭文件*/
//STL標準容器使用初始化列表 vector<string> s = {"hello","C++","11"};
能夠看到在引入了std::initializer_list特性以後,初始化變量的工做簡潔了許多,很是方便。函數
2.自動類型推導學習
類型推導能夠在編譯的時候自動來識別對象的類型,從而簡化代碼,更好的使用模版編程,使用auto關鍵字便可自動推導類型明確的變量,例如:this
/*自動類型推導*/ vector<int> v; vector<int>::iterator it=v.begin(); //使用類型推導前 auto it2 = v.begin(); //使用類型推導後
decltype也能夠根據已有的對象自動識別類型,可是它和auto的不一樣之處是:auto是自動推導出表達式右邊的類型,而decltype是自動推導出任意一個變量的類型,而且能夠用該類型來定義變量,提及來比較難理解,看下面的代碼就一目瞭然了:spa
int num; decltype(num) b = 5;
3.自動範圍推導指針
在C++11之前,寫一個循環語句一般是這樣的:
for (int i = 0; i < 10; i++){ //使用自動範圍推導前 cout << i << endl; }
而在C++11中,for語句新增了範圍迭代的寫法,該寫法能夠簡化for循環的代碼,「:」符號左邊是要編歷的元素類型,能夠是引用或者const引用類型;而「:」右邊是要編歷的容器能夠是數組或者STL容器等,代碼以下:
int arr []= { 1, 2, 3, 4, 5 }; //使用自動範圍推導後 for (int &i : arr){ cout << i << endl; }
4.智能指針和空指針
智能指針是一個類而並不是是普通的指針,shared_ptr是一引用計數指針,一個shared_ptr只有在已經沒有任何其餘shared_ptr指向其本來所指向的對象時,纔會銷燬該對象。
除了shared_ptr以外,還有weak_ptr,可是weak_ptr並不擁有其所指向的對象,所以不影響該對象的銷燬與否,也不能對weak_ptr解引用,只能判斷該指針是否已經被銷燬。下面舉個例子說明一下shared_ptr:
/*智能指針和空指針*/ //智能指針只能被智能指針賦值,不能用shared_ptr<int> pq= new int; shared_ptr<int> p1(new int); //用{ }進入一個新的做用域 { //新的智能指針指向p1,這是至關於對int內存塊的一次retain shared_ptr<int> p2 = p1; *p2 = 123; //p2被銷燬,至關於對int內存塊的一次release,可是因爲p1還指向該內存,引用計數器不爲0,所以不會釋放 } return 0; //p1也被銷燬,此時引用計數爲0,int所佔用的內存被自動回收 /*注意!使用shared_ptr須要include <memory>*/
若是將share_ptr定義爲類的成員變量,那麼此智能指針的retain引用會在該對象被釋放的時候才釋放。
空指針nullptr的存在是爲了解決NULL的二義性問題,由於NULL也能夠表明0,nullptr的類型爲nullptr_t,能隱式轉換爲任何指針或者是成員指針的類型,也能和它們進行相等或者不等的比較。而nullptr不能隱式轉換爲整數,也不能和整數作比較。
void foo(char *); void foo(int); foo(NULL); //調用的是void foo(int); foo(nullptr); void foo(char *);
5.Lambda特性
lambda表達式是一個很是好的新特性,當你須要在程序中添加一個新的臨時函數時,直接使用Lambda函數,會讓你感受到原來寫程序還能夠這麼爽~(相似於Java中的 匿名內部類)。lambda的寫法以下:
[函數外部對象參數] (函數參數) -> 返回值類型{ 函數體}
(1)[ ]中的函數外部對象參數,容許在函數體內直接調用函數外部的參數;
(2)( )中的參數,同正常函數的參數沒有什麼差別,是每次函數調用時傳入的變量;
(3)->後面跟着函數返回值的類型;
(4){ }裏面能夠編寫邏輯函數,並使用[ ]和( )傳入的參數
定義在lambda函數相同做用域的參數引用也能夠被使用,這種參數集合通常被稱爲閉包,[ ]中能夠填寫下面的幾種類型的參數,將定義lambda函數做用域內的變量傳入函數體中。
1.[ ]能夠沒有任何參數,這種狀況下不傳入外部參數
2.[a,&b]傳入變量a的值以及變量b的引用
3.[&]以引用的方式傳入全部的變量
4.[=]以傳值的方式傳入全部的變量,值不能夠被修改
5.[&,a]除了a用傳值的方式,其餘變量都已引用的方式傳入
6.[=,&a]除了a用引用的方式傳入,其餘變量都以傳值的方式傳入
下面讓咱們經過一個例子來了解一下,當在lambda中使用了「=」傳入的參數,且對引用參數或者外部參數進行賦值操做以後,會產生意想不到的結果,而且還需注意在使用「&」時須要注意引用對象的生命週期。
/*Lambda表達式*/ int b, c, d; auto func0 = [&]()->void {b = 1; c = 2; d = 3; }; auto func1 = [=]()->int {return 2 * 3; }; auto func2 = [=, &b, &c]()->void {++b; c += d + b; }; auto func3 = [=]()->int {return b + d; }; func0(); //b,c,d分別爲1,2,3 c=func1(); //c=6 func2(); //b=2;c=858993456,d=6; b = func3();//b=1717986916 return 0;
當Lambda被定義在類的成員函數中時,Lambda能夠調用該類的private函數;當Lambda調用該類的成員函數時,操做成員變量或者其餘成員函數時,須要將this傳入,=和&會傳入this。
使用std::function能夠存儲Lambda函數,好比能夠用function<void()>來存儲func0,用function<int()>來存儲func1,帶有參數的函數能夠直接在()內輸入參數類型,在使用function時要包含頭文件functional。
#include <functional> function<void()> f1 = func0; function<int()>f2 = func1;
function還能夠用於存放普通函數,靜態函數和類的公有成員函數,前二者和lambda的用法同樣,直接將函數名賦值給function對象便可(沒法識別重載的函數),但類的成員函數須要使用bind來綁定:
ClassA *obj = new ClassA(); function<void(int)> f2 = bind(&ClassA::memberFunc1,obj,std::placeholders::_1); function<void(int, char)>f3 = bind(&ClassA::memberFunc2,obj,std::placeholders::_2);
使用bind函數綁定成員函數和對象指針,使用std::placeholders佔位符來表示函數的參數數量,其後綴依次從1~N。
6.顯式虛函數重載
override能夠確保在重寫父類的虛函數,調整父類的虛函數時(更名字或者參數),不會忘記調整子類的虛函數。在編譯時,編譯器會爲標記爲override的虛函數檢查其父類是否有該虛函數:
class B{ public: virtual void virtuaalFunc(int); }; class C{ public: virtual void virtuaalFunc(int) override; //顯示重寫父類虛函數 virtual void virtuaalFunc(char) override; //錯誤 };
final能夠保證子類不能重寫函數,不能具備相同簽名的函數,或者類不能被繼承。(相似於Java中final用法)override和final並非C++11的關鍵字,只是在特定的位置纔有特殊的含義,在其餘地方仍然是看成變量來用的。
做者:馬三小夥兒
出處:http://www.cnblogs.com/msxh/p/5869992.html 請尊重別人的勞動成果,讓分享成爲一種美德,歡迎轉載。另外,文章在表述和代碼方面若有不妥之處,歡迎 批評指正。留下你的腳印,歡迎評論!