C++中的列表初始化是一種用一對花括號 {} 來進行對象初始化的語法。它被引入主要是為了提供一種統一的初始化方式,適用于各種不同的數據類型和數據結構,包括基本類型、數組、結構體、類、STL 容器等。列表初始化在 C++11 標準中被引入,是現代 C++ 編程風格的一部分。
Type variable = {value1, value2, ...};
int x = {42};double y = {3.14};
int arr[] = {1, 2, 3, 4, 5};
struct Point { int x; int y;};Point p = {10, 20};
class MyClass {public: int data; double value; MyClass(int d, double v) : data(d), value(v) {}};MyClass obj = {42, 3.14};
#include <vector>#include <map>std::vector<int> vec = {1, 2, 3, 4, 5};std::map<int, std::string> myMap = {{1, "one"}, {2, "two"}};
class MyType {public: int x; double y; MyType(int a, double b) : x(a), y(b) {}};MyType myVar = {5, 2.5};
窄轉化(Narrowing Conversion)指的是將一個具有較大范圍的值轉換為較小范圍的類型時可能丟失信息的情況。這種轉換可能導致截斷或失真,因為目標類型的表示范圍比源類型小。在 C++ 中,窄轉化是一種不安全的類型轉換,因為它可能導致數據丟失或意外的行為。
以下是一些示例說明窄轉化:
double myDouble = 3.14;int myInt = myDouble; // 窄轉化,可能會截斷小數部分
long long myLong = 1000000000000;int myInt = myLong; // 窄轉化,可能會截斷或溢出
long long myLong = 1000000000000;int myInt = static_cast<int>(myLong); // 窄轉化,可能會截斷或溢出
窄轉化是需要小心處理的,因為它可能導致數據的損失和不確定的行為。在需要進行類型轉換時,最好使用安全的轉換方式,例如使用 static_cast 并在可能丟失信息的地方進行顯式的檢查和處理。在 C++11 引入的列表初始化中,提供了對縮窄轉換的更嚴格的檢查,不允許在列表初始化時發生縮窄轉換,從而幫助程序員避免潛在的問題。
列表初始化有一些規則和特點,主要包括以下幾個方面:
列表初始化對類型轉換更為嚴格,不允許發生縮窄轉換,即不允許將一個精度更高的類型賦值給一個精度較低的類型。
int x = {3.14}; // 錯誤,嘗試縮窄轉換
int arr[] = {1, 2, 3}; // 合法,數組大小為3
當列表初始化的類型和目標類型不匹配時,如果存在適當的構造函數,編譯器會嘗試調用構造函數進行初始化。
class MyClass {public: int data; double value; MyClass(int d, double v) : data(d), value(v) {}};MyClass obj = {42, 3.14}; // 合法,調用構造函數
在某些情況下,可以使用空的花括號 {} 進行初始化,這會被解釋為對應類型的默認值。
int x = {}; // x 被初始化為 0double y = {}; // y 被初始化為 0.0
當進行列表初始化時,編譯器會根據構造函數的參數匹配規則選擇相應的構造函數。
class Example {public: Example(int a, double b); Example(std::string str);};Example obj1 = {42, 3.14}; // 調用構造函數 Example(int, double)Example obj2 = {"Hello"}; // 調用構造函數 Example(std::string)
可以使用嵌套的列表初始化來初始化嵌套的數據結構。
std::vector<std::vector<int>> matrix = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
總體來說,列表初始化提供了一種簡潔且直觀的初始化語法,同時對類型匹配和轉換有著更為嚴格的規定,減少了一些初始化時可能發生的錯誤。
列表初始化(Uniform Initialization)在 C++ 中引入的好處主要有以下幾點:
int x = {42}; // 初始化基本類型int arr[] = {1, 2, 3}; // 初始化數組Point p = {10, 20}; // 初始化結構體MyClass obj = {42, 3.14}; // 初始化類std::vector<int> vec = {1, 2, 3}; // 初始化容器
int x = {3.14}; // 錯誤,嘗試縮窄轉換
class MyClass {public: int data; double value; MyClass(int d, double v) : data(d), value(v) {}};MyClass obj = {42, 3.14}; // 調用構造函數
int arr[] = {1, 2, 3}; // 合法,簡潔
"Most Vexing Parse" 是一個有趣而令人困擾的 C++ 編程問題,它通常發生在類的對象聲明上,導致程序員可能不是按照他們預期的方式初始化對象。這個問題的名字來源于這種情況的令人迷惑和難以理解。
Most Vexing Parse 主要發生在下面這樣的情況:
class MyClass {public: MyClass() {}};int main() { MyClass obj(); // 最令人迷惑的解析,聲明了一個函數而不是對象 // ... return 0;}
在上述代碼中,MyClass obj(); 被編譯器解釋為聲明一個返回 MyClass 類型的函數而不是創建一個 MyClass 類型的對象。這是因為在 C++ 中,如果聲明一個函數的時候帶有空括號,編譯器會將其解釋為一個函數聲明而不是一個對象定義。
為了避免 most vexing parse,可以使用以下兩種方式之一:
MyClass obj{}; // 使用花括號初始化,避免 most vexing parse
MyClass obj(); // 編譯器會將其解釋為函數聲明MyClass obj{}; // 使用括號初始化,避免 most vexing parse
這個問題是由 C++ 語法規則引起的,對于初學者來說可能會令人困擾。因此,在聲明和初始化對象時,特別是在有可能發生 most vexing parse 的地方,建議使用花括號初始化或括號初始化,以避免潛在的問題。
1、類型是一個普通數組,如int[5],char[],double[]等
2、類型是一個類,且滿足以下條件:
class NotAggregate {public: int x; int y; NotAggregate(int a, int b) : x(a), y(b) {}};NotAggregate obj = {1, 2}; // 錯誤,NotAggregate 不是聚合類型
double myDouble = 3.14;int myInt = myDouble; // 合法,但列表初始化會報錯
class MyClass {public: MyClass() {}};MyClass obj(); // 最令人迷惑的解析,聲明了一個函數而不是對象MyClass obj{}; // 正確的初始化方式
總之,雖然列表初始化是一種很便捷和安全的初始化方式,但在某些情況下,特別是對于非聚合類型和可能導致 most vexing parse 的地方,可能需要考慮其他的初始化方式。
本文鏈接:http://www.www897cc.com/showinfo-26-76573-0.htmlC++中列表初始化,你知多少?
聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。郵件:2376512515@qq.com
上一篇: 怎樣設計全鏈路壓力測試平臺?