C++11中隱式類(lèi)型轉(zhuǎn)換的實(shí)現(xiàn)示例
1. 關(guān)于C++11
1.1 C++11簡(jiǎn)介
在2003年C++標(biāo)準(zhǔn)委員會(huì)曾經(jīng)提交了一份技術(shù)勘誤表(簡(jiǎn)稱TC1), 使得 C++03 這個(gè)名字已經(jīng)取代了 C++98 成為 C++11 之前的最新C++標(biāo)準(zhǔn)名稱。
不過(guò)由于 C++03(TC1) 主要是對(duì) C++98 標(biāo)準(zhǔn)中的漏洞進(jìn)行修復(fù),語(yǔ)言的核心部分則沒(méi)有改動(dòng),因此人們習(xí)慣性的把兩個(gè)標(biāo)準(zhǔn)合并稱為 C++98/03 標(biāo)準(zhǔn)。從 C++0x 到C++11,C++ 標(biāo)準(zhǔn)10年磨一劍,第二個(gè)真正意義上的標(biāo)準(zhǔn)珊珊來(lái)遲。
相比于 C++98/03,C++11 則帶來(lái)了數(shù)量可觀的變化,其中包含了約 140 個(gè)新特性,以及對(duì) C++03 標(biāo)準(zhǔn)中約 600 個(gè)缺陷的修正,這使得 C++11 更像是從 C++98/03 中孕育出的一種新語(yǔ)言。相比較而言,C++11 能更好地用于系統(tǒng)開(kāi)發(fā)和庫(kù)開(kāi)發(fā)、語(yǔ)法更加泛華和簡(jiǎn)單化、更加穩(wěn)定和安全,不僅功能更強(qiáng)大,而且能提升程序員的開(kāi)發(fā)效率,公司實(shí)際項(xiàng)目開(kāi)發(fā)中也用得比較多,所以我們要認(rèn)真去學(xué)習(xí)。
1.2 C++11官方介紹
??官網(wǎng)鏈接: C++11
2. 統(tǒng)一的列表初始化
2.1 C/C++98 數(shù)組 & 結(jié)構(gòu)體 初始化
在C/C++98中,標(biāo)準(zhǔn)允許使用花括號(hào) { } 對(duì)數(shù)組或者結(jié)構(gòu)體元素進(jìn)行統(tǒng)一的列表初始值設(shè)定。比如:
struct Point
{
int _x;
int _y;
};
int main()
{
// struct Point類(lèi)型的初始化
Point p = { 100, 99 };
int arr1[10] = { 10, 20, 30 };
return 0;
}
2.2 單/多參數(shù)類(lèi)型的隱式類(lèi)型轉(zhuǎn)換
對(duì)于自定義類(lèi)型,如果是單參數(shù)類(lèi)型的構(gòu)造函數(shù),會(huì)發(fā)生隱式類(lèi)型轉(zhuǎn)換,例如:
class A
{
public:
A(int x)
: _x(x)
, _y(x)
{}
void Print()
{
cout << _x << ":" << _y << endl;
}
private:
int _x;
int _y;
};
int main()
{
// 隱式類(lèi)型轉(zhuǎn)換
A aa1 = 1;
A aa2 = { 2 };
// 直接構(gòu)造
A aa3(3);
// 也可以省略等號(hào)
A aa4{ 1 };
return 0;
}
如果是多參數(shù)類(lèi)型的構(gòu)造函數(shù),同樣會(huì)發(fā)生隱式類(lèi)型轉(zhuǎn)換,例如:
class A
{
public:
A(int x, int y)
: _x(x)
, _y(y)
{}
private:
int _x;
int _y;
};
int main()
{
// 隱式類(lèi)型轉(zhuǎn)換
A aa1 = { 1, 2 };
// 也可以省略等號(hào)
A aa2{ 3, 4 };
// 可以省略等號(hào)
A aa3(4, 5);
return 0;
}
如果不想發(fā)生隱式類(lèi)型的轉(zhuǎn)換,可以在構(gòu)造函數(shù)之前加上 explicit 關(guān)鍵字,例如:
class A
{
public:
// 不允許發(fā)生隱式類(lèi)型轉(zhuǎn)換
explicit A(int x, int y)
: _x(x)
, _y(y)
{}
// 不允許發(fā)生隱式類(lèi)型轉(zhuǎn)換
explicit A(int x)
: _x(x)
, _y(x)
{}
void Print()
{
cout << _x << ":" << _y << endl;
}
private:
int _x;
int _y;
};
int main()
{
// 下面兩行會(huì)報(bào)錯(cuò)
A aa0 = 1;
A aa3 = { 1 };
A aa1 = { 1, 2 };
// 以下可以正常使用
A aa2{ 3, 4 };
A aa4{ 0 };
return 0;
}
關(guān)于單/多參數(shù)類(lèi)型的構(gòu)造函數(shù)的解釋:
對(duì)于形如 A aa1 = { 1, 2 };的構(gòu)造,編譯器處理時(shí)會(huì)發(fā)生以下兩個(gè)步驟:
首先會(huì)利用 { } 中的值調(diào)用構(gòu)造函數(shù)生成一個(gè)臨時(shí)變量;
對(duì) aa1 進(jìn)行拷貝構(gòu)造。
但是編譯器會(huì)優(yōu)化成直接構(gòu)造。
對(duì)于形如 A aa2{ 3, 4 };的構(gòu)造,就會(huì)直接調(diào)用構(gòu)造函數(shù),不會(huì)產(chǎn)生臨時(shí)變量。
如果產(chǎn)生了臨時(shí)變量,我們知道臨時(shí)變量具有常性,就有:
- 如果用:
A& aa1 = { 1, 2 };會(huì)報(bào)錯(cuò)。 - 得用:
const A& aa1 = { 1, 2 };
3. STL 中的 Initializer_list 構(gòu)造函數(shù)
我們這里先以 vector 為例。
3.1 Initializer_list
initializer_list 是 C++11 引入的一種標(biāo)準(zhǔn)庫(kù)類(lèi)型,用于方便地初始化同一種類(lèi)型的元素列表。initializer_list 允許通過(guò)大括號(hào) { } 語(yǔ)法進(jìn)行初始化,例如:
std::initializer_list<int> my_list = {1, 2, 3, 4, 5};這里 my_list 是一個(gè)包含了整數(shù)元素 {1, 2, 3, 4, 5} 的 initializer_list<int> 對(duì)象。
主要特點(diǎn)包括:
- 不可變性: 一旦初始化完成,
initializer_list中的元素不可再被修改。 - 輕量:
initializer_list本身只包含指向數(shù)據(jù)的指針和長(zhǎng)度信息,因此非常輕量,適合在函數(shù)參數(shù)傳遞和對(duì)象構(gòu)造時(shí)使用。 - 語(yǔ)法簡(jiǎn)潔: 通過(guò)
{ }初始化列表的語(yǔ)法,能夠清晰地指定一組初始值,而不需要顯式地調(diào)用構(gòu)造函數(shù)。
底層實(shí)現(xiàn)邏輯:
namespace std
{
template<class T>
class initializer_list
{
public:
using value_type = T;
using reference = const T&;
using const_reference = const T&;
using size_type = size_t;
initializer_list() noexcept; // 構(gòu)造一個(gè)空的 initializer_list
size_type size() const noexcept; // 返回列表中元素的個(gè)數(shù)
const T* begin() const noexcept; // 返回指向第一個(gè)元素的指針
const T* end() const noexcept; // 返回指向最后一個(gè)元素之后的位置的指針
};
}
3.2 Initializer_list 初始化容器
當(dāng)使用vector時(shí),每次都用不同數(shù)量的值初始化容器,那么就要寫(xiě)非常多的構(gòu)造函數(shù)來(lái)實(shí)現(xiàn)這個(gè)需求。
但是用Initializer_list就可以一勞永逸的解決這個(gè)問(wèn)題。
int main()
{
// 用 10 個(gè) 1 構(gòu)造 vector
vector<int> v(10, 1);
initializer_list<int> il = { 10,9,8,5 };
vector<int>(il);
vector<int> v1 = { 1,2,3,4,5,6 };
vector<int> v2({ 9,8,7,6,5,4 });
return 0;
}
兩種構(gòu)造的區(qū)別:
對(duì)于:vector<int> v1 = { 1,2,3,4,5,6 };
- 編譯器會(huì)先將
{ 1,2,3,4,5,6 }識(shí)別成initializer_list; - 然后調(diào)用
Initializer_list的構(gòu)造,中間生成臨時(shí)變量; - 最后拷貝構(gòu)造給
v1; - 但是編譯器會(huì)優(yōu)化成直接構(gòu)造。
對(duì)于:vector<int> v2({ 9,8,7,6,5,4 });
- 這就是直接構(gòu)造。
- 總的來(lái)說(shuō),形如:
X自定義 = Y類(lèi)型一定發(fā)生了 隱式類(lèi)型轉(zhuǎn)換。X 支持 Y 為參數(shù)類(lèi)型構(gòu)造就可以。
對(duì)于 map 的 initializer_list 的構(gòu)造
map 支持 pair 類(lèi)型的 initializer_list 的構(gòu)造:

這里的 value_type 就是 pair。
map構(gòu)造代碼示意:
int main()
{
// 方法一:
pair<string, string> kv1 = { "include", "包括" };
pair<string, string> kv2 = { "sort","排序" };
map<string, string> dict1({ kv1, kv2 });
// 方法二:
map<string, string> dict2 = { kv1, kv2 };
map<string, string> dict3 = {{"include", "包括"}, { "sort","排序" }};
return 0;
}
兩種構(gòu)造區(qū)別:
對(duì)于方法一:
- 因?yàn)?code>pair支持雙參數(shù)的構(gòu)造函數(shù),所以
{ "include", "包括" }、{ "sort","排序" }會(huì)發(fā)生隱式類(lèi)型的轉(zhuǎn)換生成臨時(shí)變量,然后再拷貝構(gòu)造給kv1,kv2(編譯器會(huì)優(yōu)化成直接構(gòu)造); - 因?yàn)?code>map 支持
pair類(lèi)型的initializer_list的構(gòu)造,因此直接使用:map<string, string> dict1({ kv1, kv2 });即可
對(duì)于方法二:
{"include", "包括"}, { "sort","排序" }會(huì)被識(shí)別成兩個(gè)pair類(lèi)型;- 然后外層大括號(hào)會(huì)被識(shí)別成
initializer_list,進(jìn)行隱式類(lèi)型轉(zhuǎn)換,在進(jìn)行拷貝構(gòu)造(會(huì)被優(yōu)化)。
到此這篇關(guān)于C++11中隱式類(lèi)型轉(zhuǎn)換的實(shí)現(xiàn)示例的文章就介紹到這了,更多相關(guān)C++11 隱式類(lèi)型轉(zhuǎn)換內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C語(yǔ)言數(shù)據(jù)結(jié)構(gòu)之單向鏈表詳解分析
鏈表可以說(shuō)是一種最為基礎(chǔ)的數(shù)據(jù)結(jié)構(gòu)了,而單向鏈表更是基礎(chǔ)中的基礎(chǔ)。鏈表是由一組元素以特定的順序組合或鏈接在一起的,不同元素之間在邏輯上相鄰,但是在物理上并不一定相鄰。在維護(hù)一組數(shù)據(jù)集合時(shí),就可以使用鏈表,這一點(diǎn)和數(shù)組很相似2021-11-11
淺談c++性能測(cè)試工具google benchmark
本文將會(huì)介紹如何使用模板以及參數(shù)生成器來(lái)批量生成測(cè)試用例,簡(jiǎn)化繁瑣的性能測(cè)試代碼2021-06-06
利用C語(yǔ)言實(shí)現(xiàn)猜數(shù)字游戲
這篇文章主要為大家詳細(xì)介紹了利用C語(yǔ)言實(shí)現(xiàn)猜數(shù)字游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-02-02
關(guān)于C++中由于字節(jié)對(duì)齊引起內(nèi)存問(wèn)題定位分析
前幾天遇到一個(gè)稀奇古怪的問(wèn)題,在創(chuàng)建對(duì)象的時(shí)候程序異常退出,查找代碼發(fā)現(xiàn)結(jié)構(gòu)體數(shù)組問(wèn)題,最終把問(wèn)題簡(jiǎn)化得到解決方法,下面小編把我的問(wèn)題及解決方案分享到腳本之家平臺(tái)供大家參考下2021-06-06
c++實(shí)現(xiàn)超簡(jiǎn)單的貪吃蛇游戲?qū)嵗榻B
大家好,本篇文章主要講的是c++實(shí)現(xiàn)超簡(jiǎn)單的貪吃蛇游戲?qū)嵗榻B,感興趣的同學(xué)趕快來(lái)看一看吧,對(duì)你有幫助的話記得收藏一下,方便下次瀏覽2021-12-12
C語(yǔ)言編程C++動(dòng)態(tài)內(nèi)存分配示例講解
這篇文章主要介紹了C語(yǔ)言編程C++動(dòng)態(tài)內(nèi)存分配示例講解,為什么存在動(dòng)態(tài)內(nèi)存分配?本文通過(guò)動(dòng)態(tài)內(nèi)存介紹及常見(jiàn)內(nèi)存錯(cuò)誤等示例來(lái)為大家講解2021-09-09

