条款7-C++注意区分()和{}

05/13/2020

C++初始化的多样性

int x(0);
int x = 0;
int x{0};
**加粗样式**int x = {0};//通常来说,编译器把它当成是 int x{0};来处理

初始胡不等于赋值

int x = 0;

对于以上例子,有人会看出是初始化并赋值,其实并没有赋值操作。其实初始化和赋值是关于调用不同函数完成的。

用户自定义对象的创建

Widget w1;
Widget w2 = w1; //调用拷贝构造函数
w1 = w2; 		//调用拷贝赋值运算符

统一初始化

  • 形式花括号

用途

  • 初始化列表
  • 非静态成员指定默认初始化值
  • 不可复制的对象

唯一不可行

禁止内建型别之间进行隐式窄化型别转换(narrowing conversion)

  • 内建型别:int,float,double内置类型;比如double隐式转int。
double x,y,z;
int sum{ x + y + z };//错误的

花括号与默认构造函数

Widget w1{}; //默认初始化对象实例 == Widget w1;
Wodget w2(); //被声明为函数,这是错误的

花括号与std::initializer_list 之间匹配问题

例子1:

class Widget
{
public:
	Widget(int i, bool b);
	Widget(int i,double d);
	Widget(std::initializer_list<long double> il);
};
Widget w1(10,true);
Widget w2{10,true}; //会被调用initializer_list这个构造函数,10和true被强制转型为long double

例子2:窄化型别转换

class Widget
{
public:
	Widget(int i, bool b);
	Widget(int i,double d);
	Widget(std::initializer_list<bool> il);

	
};

//编译错误 因为只会匹配到initializer_list这一个构造函数,
//而要求把一个int(10)和一个double(5.0)强制转换为bool类型,在花括中不被允许,因为是窄化的。
Widget w2{10,5.0}; 

例子3:

class Widget
{
public:
	Widget(int i, bool b);
	Widget(int i,double d);
	Widget(std::initializer_list<long double> il);//重载类型转换运算符
	//没有返回类型和形参,必须是成员函数
	//可以转换任意类型,除了void,数组与函数,但是指针可以
	operator float()const;  //Widget类型强制转换为float类型
};


Widget w2{10,5.0}; 
Widget w3{w2};// 调用initializer_list, w4被强制转换成float类型,再转换为double类型

要点

  • 花括号应用广泛,可以阻止隐式窄化型别转换,还对令人苦恼之解析语法免疫
  • 构造函数重载决议期间,只要右任何可能,花括号初始胡就会与std::initializer_list型别的形参相匹配
  • 使用小括号还是花括号结果是不一样的,参加vector类
  • 再模板内容进行对象创建,到底应该使用小括号还是花括号会成为一个棘手的问题

Effective Modern C++ 第五版(中文版)条款7

猜你喜欢

转载自blog.csdn.net/weixin_44200074/article/details/106105832