《白话C++》第7章 Page352 7.3.2初始化行为 赋值式初始化

赋值式初始化

尽管构造式初始化非常有格调,但对于简单变量,更常见的还是采用等号完成初始化:

int i1 = 1;
char c = 'C';
float f = 89.5F;

看起来很像在赋值,但因为是在定义的过程中执行的,因此采用等号来初始化,和使用圆括号的方式效果是一样的。

可以将“赋值式初始化”当成是初始化的“世俗”版本,在字面上,容易令人误解为赋值。

“赋值式初始化”还有一个问题:只允许使用一个数据作为初始化条件。

比如Point类有一个需要两个入参的构造函数,使用构造式初始化非常方便:

Point pt(45, 190);

没办法改为直接使用赋值式初始化的语法完成相同操作:

Point pt = 45, 190; //语法错误(再往后,会找到某种变通的解决方法)

另外,创建堆对象时,指针指向可以使用赋值式初始化,但所指向的数据本身,无法统一采用赋值式初始化,比如创建一个int类型指针,并初始化所指向的数据为5;

int* pI = new int(5);

非要将对int的初始化也使用“=”完成,语法应该是:

*(int pI = new int) = 5; //语法错误

这不仅语法错误,而且太丑了。

赋值式初始化语句的三个问题:

(1)看起来容易误解成赋值;

(2)不支持需要多个入参的构造;

(3)不支持堆对象的双重初始化。

对于类或结构体,“赋值式初始化”是否和“构造式初始化”完全等效还依赖于编译器的具体实现,比如有这样一个结构体:

struct A
{
    A(int i){/*空*/}
};

接下来使用赋值式初始化创建一个新对象:

A a = 5;

编译之后,可能是两种效果,其对比如表7-11所列。

表7-11 “构造和赋值”操作合并优化效果
未优化(两步操作)优化(合并为一步)

A tmp(5);//先构造一个临时对象

//再从临时对象复制到目标对象

A a(tmp);

//直接使用5构造出目标对象

A a(5);

基本上主流编译器都默认使用优化方案,这确实是一个优化行为,对于g++,加上“-fno-elide-constructors”选项后,将回到未优化的低性能版本。

结论:赋值式初始化在内置类型上使用,有其世俗意义,但在类或结构体上使用,弊大于利

有一个办法可以让类对象构造时,干脆不允许使用赋值式初始化的语法。只需为类的单入参构造函数加上“explicit”修饰:

struct A
{
    explicit A(int i)
    {}
};

接下来使用赋值式初始化创建一个新对象:

A a = 5; //ERROR

explicit”意为“清楚明白,易于理解的”。反过来说,用着赋值的语法,行着构造函数的行为,是“不清不楚、不明不白、不易理解的”。加上explicit关键字修饰的构造函数,称为“显式的”构造函数

现在我们知道,显式构造可用于避免和赋值操作符“=”之间不清不楚、背地里的关系。

  • 6
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值