【读书笔记】【深入应用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中不会报错。

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