05/13/2020
C++再创建对象时注意区分()和{}
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