文章目錄
- 引言
- 一、列表初始化
- 1.1 內置類型
- 1.2 結構體或類
- 1.3 容器
- 二、聲明
- 2.1 auto
- 2.2 decltype
- 2.3 nullptr
- 三、STL的變化
- 3.1 新增容器
- 3.2 新增initializer_list構造
- 3.3 新增移動構造、移動賦值和移動插入
- 3.4 其他
引言
關于C++11的auto、nullptr和范圍for的知識,在之前已經提到過,這里不再贅述,有需要的請移步這篇博客【C++練級之路】【Lv.1】C++,啟動!(命名空間,缺省參數,函數重載,引用,內聯函數,auto,范圍for,nullptr)
一、列表初始化
C++11更新后,一切皆可用列表初始化。列表初始化,又稱統一初始化,具體使用{}進行初始化。
列表初始化,沿襲C語言對于內置類型和結構體的初始化上,進行了統一形式的擴展。
1.1 內置類型
void test()
{//單一變量int i = 0;int j = { 0 };int k{ 0 };//數組int arr1[] = { 1,2,3 };int arr2[5]{ 0 };//動態開辟int* ptr1 = new int[5] {0};
}
雖然內置類型(如 int, double 等)通常不需要列表初始化,但列表初始化仍然允許。列表初始化的一個特點,就是可以去除等號“=”。
1.2 結構體或類
struct Point
{int _x, _y;
};class Date
{
public:Date(int year, int month, int day): _year(year), _month(month), _day(day){}
private:int _year, _month, _day;
};void test()
{//結構體Point p1 = { 3,5 };Point p2{ 4,6 };//類Date d1(2024, 4, 10);Date d2 = { 2024,5,1 };Date d3{ 2024,6,1 };//動態開辟Date* ptr2 = new Date[3]{ d1,d2,d3 };Date* ptr3 = new Date[3]{ {2024,1,1},{2024,2,2},{2024,3,3} };
}
對于類的列表初始化,可以理解為隱式類型轉換:構造臨時對象->拷貝構造->編譯器優化為直接構造。
1.3 容器
void test()
{vector<int> v1 = { 1,2,3 };vector<int> v2 = { 1,2,3,4,5 };map<string, string> dict = { {"排序","sort"},{"逆序","reverse"} };
}
對于容器的列表初始化,可不是之前的類型轉換,因為此時初始化的列表是可以變長的,而之前的多參數構造是固定長度的。
那么,此時應該怎么理解容器的列表初始化呢?其實,這里涉及了STL庫中的initializer_list類。
void test()
{auto il = { 1,2,3,4,5 };cout << typeid(il).name() << endl;initializer_list<int>::iterator it = il.begin();while (it != il.end()){cout << *it << " ";++it;}cout << endl;for (auto e : il){cout << e << " ";}cout << endl;
}
由上述代碼可知,讓編譯器自動推導列表類型,便是class std::initializer_list< int >。同樣的,initializer_list類也有自己的迭代器,可以用迭代器進行遍歷和修改。
那么,每次容器的列表初始化過程可以理解為:將右側構造為initializer_list ->遍歷initializer_list,進行迭代器區間構造。
- 構造initializer_list的過程:在常量區找到列表中的值,用兩個指針start和finish指向頭部和尾部的下一位(類似于vector的內部原理)
- 每個容器都添加了initializer_list的構造函數,調用對應的構造函數,運用迭代器區間進行容器構造
ps:容器既有initializer_list的構造,也有initializer_list的賦值
二、聲明
C++11提供了多種簡化聲明的方式,尤其是在使用模板時。
2.1 auto
2.2 decltype
關鍵字decltype可將變量的類型聲明為表達式指定的類型。
void test()
{int x = 1;double y = 2.0;decltype(x) k;auto ret = x * y;vector<decltype(ret)> v;
}
decltype最大的作用,便是用來定義模板參數。因為auto沒辦法作為模板參數,所以decltype正好彌補了這方面的缺陷。
2.3 nullptr
三、STL的變化
3.1 新增容器
C++11更新了四個容器,分別是array,forward_list,unordered_set,unordered_map。其中unordered_set,unordered_map,我們已經深入學習和模擬實現過了。
那么,關于array和forward_list,其實帶來的提升較小,實際中較少用到。
- array:array是一個固定大小的容器,它在編譯時就知道自己的大小,這使得它在性能上通常優于vector,因為它不需要在運行時進行動態內存分配和大小調整。
- forward_list:forward_list是一個單向鏈表,它只包含指向下一個元素的指針,沒有指向前一個元素的指針。這使得它在內存使用上比list(雙向鏈表)更高效。
3.2 新增initializer_list構造
這點在先前列表初始化已經提到過,這是一個非常有用的提升與變化,initializer_list的引入使得 C++ 的初始化語法更加簡潔、直觀和靈活,提高了代碼的可讀性和可維護性。
3.3 新增移動構造、移動賦值和移動插入
這是非常重要的提升,可以大大提高效率。具體內容要等講到右值引用和移動語義時會詳細講解。
3.4 其他
還比如提供了cbegin和cend方法返回const迭代器等等,但是實際意義不大,因為begin和end也是可以返回const迭代器的,這些都是屬于錦上添花的操作。