C++11范圍for初始化列表auto decltype詳解
C++11新特性
1. 自動類型推導(dǎo)auto
`在C++98中auto是一個存儲類型的說明符,表明變量是局部自動存儲類型,但是局部域中定義局部的變量默認就是自動存儲類型,所以auto就沒什么價值了。
C++11中廢棄auto原來的用法,將其用于實現(xiàn)自動類型腿斷。這樣要求必須進行顯示初始化,讓編譯器將定義對象的類型設(shè)置為初始化值的類型。
1.1 基本語法
auto i = 42; // i 是 int
auto d = 3.14; // d 是 double
auto s = "hello"; // s 是 const char*
auto v = {1, 2, 3}; // v 是 std::initializer_list<int>
const auto ci = i; // const int
auto& ri = i; // int&
2. decltype
關(guān)鍵字decltype將變量的類型聲明為表達式指定的類型。
// decltype 可以推導(dǎo)出參數(shù)類型,并進行傳遞 vector<decltype(it)>v1;
decltype比auto方便的一點是decltype無需顯式實例化,也就是單純定義也行decltype還可以作為模板參數(shù)傳遞,而auto不行。
3. 列表初始化
? 在 C++11 中,初始化列表(使用花括號 {})為內(nèi)置類型和自定義類型的初始化提供了統(tǒng)一、安全的語法。下面一一列舉。
- 初始化列表 {} 是 C++11后 的推薦方式,提供類型安全和語法統(tǒng)一性。
- 構(gòu)造函數(shù)初始化 () 保留傳統(tǒng)行為,但在某些場景(如 STL 容器)可能產(chǎn)生歧義。
3.1 內(nèi)置類型
int main(){
int a{ 5 }; // 直接初始化
int b = { 10 }; // 拷貝初始化
char g{ 'A' }; // 正確,但不能超過char范圍
int* ptr1{}; // 初始化為空指針
int* ptr2{ &a }; // 指向變量a
int arr1[]{ 1, 2, 3 }; // 自動推導(dǎo)大小
int arr2[5]{ 1, 2, 3 }; // 部分初始化,剩余元素為0
char str[]{ "Hello" }; // 字符數(shù)組
std::cout << "ptr1: " << ptr1 << "\n"
<< "ptr2: " << ptr2 << "\n"
<< "str: " << str << std::endl;
return 0;
}

其實就是當內(nèi)置類型使用 { }初始化時,實際上是在調(diào)用它的構(gòu)造函數(shù)進行構(gòu)造這就不奇怪了,無非就是讓內(nèi)置類型將 { } 也看做一種特殊的構(gòu)造:構(gòu)造+賦值 優(yōu)化為直接構(gòu)造我們可以通過一個簡單的Datw類來體現(xiàn)這一現(xiàn)象。
class Date {
public:
Date(int y,int m,int d):_year(y),_month(m),_day(d){}
private:
int _year;
int _month;
int _day;
};
int main(){
Date d1 = { 0,1,1 };
return 0;
}
此時可以直接通過列表初始化{}初始化這個類。在C++11中允許省略=符號,編譯無報錯,使其與拷貝構(gòu)造函數(shù)一樣。使用關(guān)鍵字·explicit·可以避免編譯器隱式轉(zhuǎn)換。

這樣編譯器無法優(yōu)化,便無法對d1進行構(gòu)造,自然無法完成賦值。d2相當于直接拷貝構(gòu)造函數(shù)。
即對于內(nèi)置類型來說,列表初始化 { } 實際上就相當于調(diào)用了內(nèi)置類型的構(gòu)造函數(shù),構(gòu)造出來一個對象。
3.2 自定義類型
C++11之前對于自定義類型初始化比較復(fù)雜,例如vector需要循環(huán)插入,在c++11時使用初始化列表對于自定義類型的數(shù)據(jù)操作更加方便。

3.2.1 初始化列表賦值底層
對于STL容器:
STL容器(如 vector、map、set 等)重載了 operator= 以支持 std::initializer_list,因此,可以直接用 {} 賦值:
std::vector<int>& operator=(std::initializer_list<int> il);
map<string, string> dict = { {"sort", "排序"}, {"insert", "插入"} };
std::vector<int> v;
v = {1, 2, 3}; // 調(diào)用 operator=(initializer_list<int>)
對于自定義類
如果類定義了 operator= 接受 std::initializer_list,則可以使用 {} 賦值:讓模擬實現(xiàn)的vector也支持{}初始化和賦值…
template <class T>
class vector{
public:
typedef T *iterator;
vector(initializer_list<T> l){
_start = new T[l.size()];
_finish = _start + l.size();
_endofstorage = _start + l.size();
iterator vit = _start;
typename initializer_list<T>::iterator lit = l.begin();
while (lit != l.end()){
*vit++ = *lit++;
}
}
vector<T> &operator=(initializer_list<T> l){
vector<T> tmp(l);
std::swap(_start, tmp._start);
std::swap(_finish, tmp._finish);
std::swap(_endofstorage, tmp._endofstorage);
return *this;
}
private:
iterator _start;
iterator _finish;
iterator _endofstorage;
};
- 同時提供普通構(gòu)造函數(shù)和
initializer_list構(gòu)造函數(shù)時,注意優(yōu)先級差異。
4. 范圍 for
其為C++11引入的一種簡化容器遍歷的語法,它使遍歷序列容器(如數(shù)組、vector、list 等)變得更加簡潔直觀。
基本語法:
for (類型 變量名 : 目標序列) {
// 循環(huán)體
}
如果需要修改容器中的元素,需要使用引用,這樣能夠避免發(fā)生數(shù)據(jù)拷貝影響效率。同時使用const修飾能夠避免修改原始對象。
std::vector<std::string> words = {"aaaa", "bbbb", "cccc"};
for (const auto& word : words) {//使用 & 避免拷貝,使用const避免原始數(shù)據(jù)被修改
std::cout << word << " ";
}
// 輸出:aaaa bbbb cccc
5. 智能指針
bbb", “cccc”};
for (const auto& word : words) {//使用 & 避免拷貝,使用const避免原始數(shù)據(jù)被修改
std::cout << word << " ";
}
// 輸出:aaaa bbbb cccc總結(jié)
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
C/C++?Qt?Dialog?對話框組件應(yīng)用技巧
這篇文章主要介紹了C/C++?Qt?Dialog?對話框組件應(yīng)用,這里我將總結(jié)本人在開發(fā)過程中常用到的標準對話框的使用技巧,對C++?對話框組件相關(guān)知識感興趣的朋友一起看看吧2021-11-11
Qt基礎(chǔ)開發(fā)之QString與QByteArray詳細用法與區(qū)別及QString QByteArray互轉(zhuǎn)
這篇文章主要介紹了Qt基礎(chǔ)開發(fā)之QString與QByteArray詳細用法與區(qū)別及QString QByteArray互轉(zhuǎn),需要的朋友可以參考下2020-03-03

