[C++]初始化列表构造函数VS普通构造函数

科技资讯 投稿 5900 0 评论

[C++]初始化列表构造函数VS普通构造函数

普通构造函数VS初始化列表构造函数

初始化列表构造函数最优先匹配问题

class Widget {
public:
	Widget(int i, bool b;
	Widget(int i, double d;
	Widget(std::initializer_list<long double> il;
	operator float( const; 
};

Widget w1(10, true; 	// 使⽤小括号初始化
						//调⽤第⼀个构造函数
Widget w2{10, true}; 	// 使⽤花括号初始化
						// 调⽤第三个构造函数
						// (10 和 true 转化为long double
Widget w3(10, 5.0;		// 使⽤小括号初始化
						// 调⽤第二个构造函数
Widget w4{10, 5.0};		// 使⽤花括号初始化
						// 调⽤第三个构造函数
						// (10 和 5.0 转化为long double
Widget w5(w4; 			// 使⽤小括号,调⽤拷⻉构造函数
Widget w6{w4}; 			// 使⽤花括号,调⽤std::initializer_list构造函数
Widget w7(std::move(w4; // 使⽤小括号,调⽤移动构造函数
Widget w8{std::move(w4}; // 使⽤花括号,调⽤std::initializer_list构造函数

编译器这种热衷于把括号初始化与初始化列表构造函数匹配的行为,会导致一些莫名其妙的错误

class Widget {
public:
	Widget(int i, bool b;
	Widget(int i, double d;
	Widget(std::initializer_list<bool> il; // element type is now bool
	… // no implicit conversion funcs
};
Widget w{10, 5.0}; //错误!要求变窄转换,int(10double(5.0无法转换为bool类型

只有在没有办法把{}中实参的类型转化为初始化列表时,编译器才会回到正常的函数决议流程中

std::initializer_list<std::string>代替std::initializer_list<bool>,这时⾮std::initializer_list构造函数将再次成为函数决议的候选者,因为没有办法把int和bool转换为std::string:

class Widget {
public:
Widget(int i, bool b;
Widget(int i, double d;
Widget(std::initializer_list<std::string> il;
…
};
Widget w1(10, true; // 使⽤小括号初始化,调⽤第⼀个构造函数
Widget w2{10, true}; // 使⽤花括号初始化,调⽤第⼀个构造函数
Widget w3(10, 5.0; // 使⽤小括号初始化,调⽤第⼆个构造函数
Widget w4{10, 5.0}; // 使⽤花括号初始化,调⽤第⼆个构造函数

{}空初始化列表会发生什么

假如{}内是空的,类中既有默认构造函数,也有初始化列表构造函数,此时{}会被视为没有实参,而不是一个空的初始化列表,因此会调用默认构造函数。如果就是想调用初始化列表构造函数,这应该使用{{}}的方式

class Widget {
public:
Widget(;
Widget(std::initializer_list<int> il;
...
};
Widget w1; // 调⽤默认构造函数
Widget w2{}; // 同上
Widget w3(; // 最令⼈头疼的解析!声明⼀个函数
Widget w4({}; // 调⽤std::initializer_list
Widget w5{{}}; // 同上

初始化列表带来的vector的坑

std::vector<int> v1(10, 20; 	//使⽤⾮std::initializer_list
								//构造函数创建⼀个包含10个元素的std::vector
								//所有的元素的值都是20
std::vector<int> v2{10, 20}; 	//使⽤std::initializer_list
								//构造函数创建包含两个元素的std::vector
								//元素的值为10和20

初始化列表构造函数问题带来的两点启示

    作为类库作者,如果在构造函数中重载了一个或多个初始化列表构造函数,要考虑用户使用{}初始化的情况,最好避免类似std::vector中的情况。应该尽可能做到用户无论用小括号还是花括号进行初始化都不会产生区别。一定要慎重考虑新出现的初始化列表构造函数对其他构造函数的影响!
  • 作为类库使用者,必须认真的考虑小括号和花括号之间选择创建对象的方式,最好选择其中一个从一而终

编程笔记 » [C++]初始化列表构造函数VS普通构造函数

赞同 (34) or 分享 (0)
游客 发表我的评论   换个身份
取消评论

表情
(0)个小伙伴在吐槽