【讀書筆記】【深入應用C++11】1.3 列表初始化

摘自:深入應用C++11:代碼優化與工程級應用
在C++98/03中存在着種類繁多的初始化方式。C++11爲了統一初始化方式,提出了列表初始化的概念。
#1.3.1 統一的初始化
在C++98/03中,只有普通數組和POD類型可以使用初始化列表。
【POD類型】plain old data類型,即可以直接用memcpy複製的對象。如:

int i_arr[3]={1,2,3};
struct a
{
		int x;
		int y;
}a={1,2};

在C++11中,初始化列表可以用於任何對象的初始化。

  • 對普通數組和POD類型進行初始化。
  • 之前使用()調用構造函數,可以使用初始化列表替換。
  • 在堆上分配的動態數組,可以使用初始化列表。
  • 初始化列表可以直接用在函數返回值上。 如:
struct Foo
{
		int x;
		int y;
};
int *a=new int{1};
double p=double{p};
int *arr=new int[4]{1,2,3,4};
Foo function()
{
		return {1,2};
}

在初始化時,{}前面的=書寫與否不會影響初始化的行爲。
#1.3.2 列表初始化的使用細節
對於一個聚合類型,使用初始化列表相當於對其中的每個元素分別賦值;
對於非聚合類型,需要先定義一個構造函數,使用初始化列表將調用其構造函數。
【聚合類型】的定義:

  • 類型是一個普通數組。
  • 類型是一個類(class、struct、union)且
  • 無用戶自定義的構造函數。
  • 無private和protected的非靜態數據成員
  • 無基類;
  • 無虛函數;
  • 不能有直接初始化的非靜態數據成員(GCC中可以)
    聚合類型的定義並非遞歸的,當一個類的非靜態成員是非聚合類型時,這個類也可能是聚合類型。如:
struct ST
{
		int x;
		double y;
private:
		int z;
};
struct Foo
{
		ST st;
		int x;
		double y;
};
Foo foo{{},1,2.5};

其中{}可以用來調用無參構造函數。
#1.3.3 初始化列表
##任意長度的初始化列表
爲了讓類的構造函數(或者其他函數)擁有任意長度初始化的能力,C++11在stl中引入了std::initialzer_list這個輕量級的模板。如:

class FooVector
{
public:
		FooVector(std::initializer_list<int> list)
		{
			for(auto i:list)
			{
				cout<<i<<endl;
			}
		}
};
FooVector fooVector{1,2,3,4,5};

void Function(std::initializer_list<int> list)
{
		for(auto i:vect)
		{
			cout<<i<<endl;
		}	
		return ;
}
Function({1,2,3,4,5});

##std::initialzer_list的一些細節

  • 它是一個輕量級的容器類型,iterator、size()、begin()、end();
  • std::initialzer_list可以接受任意長度的初始化列表,但元素類型必須是相同類型T;
  • std::initialzer_list的傳遞和賦值的效率高,它內部只存儲了列表中元素的引用(不需要進行值拷貝);這是它與std:vector的重要區別;
  • 因爲std::initialzer_list的元素可能是保存在函數棧中的局部變量,因此std::initialzer_list不適合做函數的返回值;而應使用std::vector。
  • std::initialzer_list只能被整體初始化或賦值。
std::initializer_list<int> func1()
{
		int a=1,b=2;
		return {a,b};//a、b在返回時沒有被拷貝,錯誤的寫法
}

std::vector<int> func2()
{
		int a=1,b=2;
		return {a,b};
}

#1.3.4 防止類型收窄
【類型收窄】導致數據內容發送變化或者精度丟失的隱式類型轉換。如:

  • 浮點數隱式轉換爲整型數;
  • 高精度浮點數隱式轉換爲低精度浮點數;
  • 整型數轉換爲浮點數,且超出了浮點數的表示範圍;
  • 長整型數轉換爲短整型數
    在C++98/03中,編譯器對於類型收窄不會報錯;
    在C++11中,列表初始化檢查類型收窄的情況,並報警告或錯誤。如:
int a=1.1;		//OK
int b={1.1};	//ERROR

const int x=1024;
const int y=1;
char c={x};		//ERROR
char d={y};		//OK

float ff=1.2;
float fd={1.2};

在fd的初始化沒有引起類型收窄,但是VS2013中會報錯,而gcc4.8中不會報錯。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章