C++11新特性
- auto關鍵字(C++11)基于范圍的for循環(C++11). 指針空值nullptr(C++11)
- C++動態內存管理
- 序列式容器 array forward_list;
- 繼承和多態:final override
- delete:不生成默認的成員函數
- default:強制編譯器生成默認的成員函數
- 智能指針:unique_ptr,shared_ptr,weak_ptr
- 哈希結構的關聯式容器:unordered系列
統一的初始化
C++98中標準允許使用花括號{}對數組元素進行統一的列表初始值設定
int array1[] = {1,2,3,4,5};
int array2[5] = {0};
對于vector容器來說不能這樣初始化
vector<int> v{1,2,3,4,5};
就無法通過編譯,導致每次定義vector時,都需要先把vector定義出來,然后使用循環對其賦初始值,非常不方便。
C++11擴大了用大括號括起的列表(初始化列表)的使用范圍,使其可用于所有的內置類型和用戶自定義的類型,使用初始化列表時,可添加等號(=),也可不添加。
內置類型花括號{}初始化
// 內置類型變量int x1 = { 10 };int x2{ 10 };int x3 = 1 + 2;int x4 = { 1 + 2 };int x5{ 1 + 2 };int x6{ x1 + x2 };// 數組int arr1[5] {1, 2, 3, 4, 5};int arr2[]{1, 2, 3, 4, 5};// 動態數組,在C++98中不支持int* arr3 = new int[5]{1, 2, 3, 4, 5};// 標準容器vector<int> v{ 1, 2, 3, 4, 5 };map<int, int> m{ { 1, 1 }, { 2, 2, }, { 3, 3 }, { 4, 4 } };
單個自定義類型列表初始化
class Point
{
public:Point(int x = 0, int y = 0) : _x(x), _y(y){}
private:int _x;int _y;
};
int main()
{//兩種初始化都可以Point p{ 1, 2 };Point p2(1, 2);return 0;
}
多個自定義類型列表初始化
多個對象想要支持列表初始化,需給該類(模板類)添加一個帶有initializer_list類型參數的構造函數即可。注意:initializer_list是系統自定義的類模板,該類模板中主要有三個方法:begin()、end()迭代器以及獲取區間中元素個數的方法size()。
template<class T>class vector{public:vector():_start(nullptr), _finish(nullptr), _endofstorage(nullptr){}vector(initializer_list<T>l):_start(new T[l.size()]){_finish = _start;for (auto e : l){*_finish++ = e;}}private:T* _start;T* _finish;T* _endofstorage;};
變量類型推導
auto推導
auto總結
decltype類型推導
auto使用的前提是:必須要對auto聲明的類型進行初始化,否則編譯器無法推導出auto的實際類型
template<class T1,class T2>
//返回的時候,返回T1和T2都不行,應該返回T1+T2后的值的類型
auto Add(const T1& left, const T2& right)
{return left + right;
}
如果能用加完之后結果的實際類型作為函數的返回值類型就不會出錯,但這需要程序運行完才能知道結果的
實際類型,即RTTI(Run-Time Type Identification 運行時類型識別)。
typeid
只能查看類型不能用其結果類定義類型dynamic_cast
只能應用于含有虛函數的繼承體系中
所以需要新的關鍵字
decltype是根據表達式的實際類型推演出定義變量時所用的類型,例如:返回值類型推演
//此處auto為占位符
//返回值類型追蹤
auto Add( T1& left, T2& right)->decltype(left+right)
{return left + right;//ret = left + right;
}int main()
{int a = 1;double b = 2.0;cout<< Add(a, b);return 0;
}
范圍for循環
范圍for
final和override
多態中總結過
智能指針
智能指針總結
新增容器----靜態數組array,forward_list以及unordered系列
委派構造函數
所謂委派構造函數:就是指委派函數將構造的任務委派給目標構造函數來完成的一種類構造的方式。
在初始化列表中調用”基準版本”的構造函數稱為委派構造函數,而被調用的”基準版本”則稱為目標構造函數。
注意:構造函數不能同時”委派”和使用初始化列表。
class Info {
public:Info() : _type(0), _name('a'){InitRSet();}Info(int type) :Info()//不能再在初始化列表中初始化其它的成員變量//,_type(type){//InitRSet();_type = type;}Info(char type) :Info(){//InitRSet();_type = type;}
private:void InitRSet() {//初始化其他變量}
private:int _type;char _name;//...
};
- 委派構造函數同時可以是目標構造函數
- 切記:環狀委派 依然可以通過編譯但是會右棧溢出
右值引用
右值引用的總結
默認函數控制
C++11讓程序員可以控制是否需要編譯器生成那些默認生成的函數
顯式缺省函數
在C++11中,可以在默認函數定義或者聲明時加上=default,從而顯式的指示編譯器生成該函數的默認版本,用=default
修飾的函數稱為顯式缺省函數。
class A
{
public:A(int a): _a(a){}// 顯式缺省構造函數,由編譯器生成A() = default;// 在類中聲明,在類外定義時讓編譯器生成默認賦值運算符重載A& operator=(const A& a);
private:int _a;
};A& A::operator=(const A& a) = default;
int main()
{A a1(10);A a2;a2 = a1;return 0;
}
刪除默認函數
如果能想要限制某些默認函數的生成,在C++98中,是該函數設置成private,并且不給定義,這樣只要其他人想要調用就會報錯。在C++11中更簡單,只需在該函數聲明加上=delete即可,該語法指示編譯器不生成對應函數的默認版本,稱=delete修飾的函數為刪除函數。
class A
{
public:A(int a): _a(a){}// 禁止編譯器生成默認的拷貝構造函數以及賦值運算符重載A(const A&) = delete;A& operator(const A&) = delete;
private:int _a;
};
int main()
{A a1(10);// 編譯失敗,因為該類沒有拷貝構造函數//A a2(a1);// 編譯失敗,因為該類沒有賦值運算符重載A a3(20);a3 = a2;return 0;
}
注意:避免刪除函數和explicit一起使用