簡介
說明
主要內容是介紹
{}
,即braces
花括號在C++11
中的作用。作用
- 默認構造和默認初始化.
- 值列表初始化。
{}
表示無參默認構造.默認值和隨機
#include <iostream> int main() { int a; int b{}; std::cout << a << std::endl; std::cout << b << std::endl; return 0; }
隨機值和默認值.
16 0 [Finished in 432ms]
結構體
#include <iostream> struct T { char a; char b; char c; char d; }; int main() { T a; T b{}; std::cout << std::hex << *(int*)&a << std::endl; std::cout << std::hex << *(int*)&b << std::endl; return 0; }
輸出都爲
0
0 0 [Finished in 436ms]
#include <iostream> typedef char (*T)[4]; int main() { T a; T b{}; std::cout << std::hex << *(int*)&a << std::endl; std::cout << std::hex << *(int*)&b << std::endl; return 0; }
輸出
10 0 [Finished in 429ms]
隨機值和默認值
0
.重載
#include <iostream> #include <vector> #include <initializer_list> struct T { T(){ std::cout << "default" << std::endl; } T(std::initializer_list<int> initial) { std::cout << "initializer_list" << std::endl; std::vector<int> temp{initial}; } }; int main() { T a; T b{}; T c{1,2,3}; return 0; }
輸出
default default initializer_list [Finished in 469ms]
匹配規則
優先匹配
std::initializer_list
構造,無參的({})
纔可以.無法構造
initializer_list
則參數拆分,匹配成員構造.對成員變量進行構造.
成員變量構造
#include <iostream> class T { public: char s[4]; }; int main() { T a{1,2,3,4}; std::cout << std::hex << *(int*)&a << std::endl; return 0; }
4030201 [Finished in 432ms]
數組和成員
#include <iostream> class T { public: char a:4; char b:4; char s[3]; }; int main() { T a{1,2,3,4}; T b{1,2,3,4,5}; std::cout << std::hex << *(int*)&a << std::endl; std::cout << std::hex << *(int*)&b << std::endl; return 0; }
40321 5040321 [Finished in 432ms]
初始化
各種初始化
int main() { int a(0); int b = 0; int c{ 0 }; int d = { 0 }; }
效果都一樣,都是初始化變量.
對等
int main() { int b = { 0 }; int c{ 0 }; }
兩種相等,後面介紹都統一用不包括
=
的.
賦值和初始化
初始化和賦值
#include <iostream> class T { public: T(char a) { std::cout << "int" << std::endl; } explicit T(T*) { std::cout << "float" << std::endl; } T(const T&) { std::cout << "cons" << std::endl; } void operator=(const T&) { std::cout << "assign" << std::endl; } }; int main() { T a = 1; //T b = nullptr; T c(nullptr); T d = a; d = a; }
執行結果是
int float cons assign D:\codes\vs\test\test\x64\Debug\test.exe (進程 9996)已退出,代碼爲 0。 要在調試停止時自動關閉控制檯,請啓用“工具”->“選項”->“調試”->“調試停止時自動關閉控制檯”。 按任意鍵關閉此窗口. . .
創建時隱式轉換爲對應的構造函數的入參.
explicit
,不允許隱式轉換.
nullptr
匹配了T*
,註釋掉的代碼因爲構造函數聲明爲explicit
所以報錯.兩個
T d=a
也被隱式的轉化爲調用構造,而下面的是賦值,則調用賦值運算函數.小結
聲明時賦值是構造,其他則賦值.
{}
轉換一下
#include <iostream> class T { public: T(char a) { std::cout << "int" << std::endl; } explicit T(T*) { std::cout << "float" << std::endl; } T(const T&) { std::cout << "cons" << std::endl; } void operator=(const T&) { std::cout << "assign" << std::endl; } }; int main() { T a{ 1 }; T b{ nullptr }; T c{(nullptr)}; T d{ a }; d = { a }; //d = { 1, a }; d = (a); d = (1, a); }
也是隱式轉換,略有差異.
int float float cons assign assign assign D:\codes\vs\test\test\x64\Debug\test.exe (進程 9400)已退出,代碼爲 0。 要在調試停止時自動關閉控制檯,請啓用“工具”->“選項”->“調試”->“調試停止時自動關閉控制檯”。 按任意鍵關閉此窗口. .
也會隱式轉換.不容易出錯.
出錯
函數還是構造
int main() { int a(); a = 2; return 0; }
無參就是函數聲明.
窄化
int main() { int a{1.0}; return 0; }
編譯報錯,因爲會窄化,即
double->int
丟失數據.窄化概念
- 基本類型之間,賦值導致了數據可能丟失.
窄化二
int main() { char a{1l}; char b{127l}; char c{128l}; return 0; }
這裏前兩個都不會,但是
128
超過了signed char
的存儲範圍.上面的浮點不能往非浮點類型轉換.
總結
匹配優先級:
initializer_list
,構造,成員.作用: 統一初始化方式,適用性廣.
注意: 默認初始化的行爲差異,
auto
的影響,空initializer_list:({})
.