C++初始化为何未调用赋值运算符且拷贝构造调用存在场景差异
问题解答
为什么初始化操作不会调用赋值运算符
在C++中,=符号出现在对象定义语句中时,属于拷贝初始化语法,不属于赋值操作,因此永远不会触发operator=的调用。
赋值操作的适用场景是:对象已经完成初始化之后,对其进行覆盖赋值,示例如下:
X a; // 完成默认构造,已经初始化 a = X(); // 对已存在的a赋值,才会调用operator=
所有初始化场景(包括直接初始化X a(b)、拷贝初始化X a = b),只会匹配调用各类构造函数,和赋值运算符没有关系。
为什么case1和case2的输出存在差异
- case2的行为逻辑:
X x2 = x1是用已经存在的左值对象x1初始化新对象x2,完全匹配拷贝构造函数的调用条件,因此会输出X(const X &)日志。 - case1的行为逻辑:
X x5 = f5()仅输出一次默认构造日志,是因为触发了返回值优化(RVO,Return Value Optimization),这是C标准允许、C17及之后版本强制要求的拷贝消除优化。
无优化的理想流程下,这段代码本该执行3步:- 执行f5函数内的局部对象
x的默认构造,输出X() - 用局部对象
x拷贝构造f5的返回值临时对象,输出X(const X &) - 用返回的临时对象拷贝构造
x5,再输出一次X(const X &)
编译器开启RVO优化后,会直接将f5内要返回的对象构造在main函数中x5对应的内存地址上,完全省略两次拷贝构造的调用,因此最终仅输出一次X()。
- 执行f5函数内的局部对象
内容的提问来源于stack exchange,提问作者HelloWorld
相关产品推荐
相关产品推荐

