为了账号安全,请及时绑定邮箱和手机立即绑定

为什么在这种情况下不调用复制构造函数?

为什么在这种情况下不调用复制构造函数?

C++
猛跑小猪 2019-07-17 18:41:23
为什么在这种情况下不调用复制构造函数?下面是代码片段:class A{public:     A(int value) : value_(value)     {         cout <<"Regular constructor" <<endl;     }     A(const A& other)   : value_(other.value_)       {         cout <<"Copy constructor" <<endl;     }private:     int value_;};int main(){     A a = A(5);}我假设输出将是“常规构造器”(对于RHS),其次是LHS的“复制构造函数”。因此,我避免了这种样式,并且总是将类的变量声明为A a(5);..但令我惊讶的是,在上面的代码中,从来没有调用过复制构造函数(Visualc+2008)。有没有人知道这种行为是编译器优化的结果,还是C+的一些有文档的(和可移植的)特性的结果?谢谢。
查看完整描述

3 回答

?
回首忆惘然

TA贡献1847条经验 获得超11个赞

我研究这个问题是为了回答另一个问题,这个问题是以欺骗的形式结束的,所以为了不让工作白费,我会回答这个问题。

表格的陈述A a = A(5)被称为复制初始化变量的a..8.5/16的C+11标准规定:

使用初始化器表达式作为参数调用所选函数;如果函数是构造函数,则调用初始化目标类型的cv非限定版本的临时函数。临时值是一个prvalue。然后,根据上述规则,调用的结果(是构造函数用例的临时结果)被用于引导初始化副本初始化的目标对象。在某些情况下,允许实现通过将中间结果直接构造到被初始化的对象来消除这种直接初始化过程中固有的复制;参见12.2,12.8。.

这意味着编译器查找要处理的适当构造函数。A(5),创建一个临时的,并将该临时副本复制到a..但是,在什么情况下,复制可以被删除呢?

让我们看看12.8/31是怎么说的:

当满足某些条件时,即使对象的复制/移动构造函数和/或析构函数有副作用,也允许实现省略类对象的复制/移动构造。在这种情况下,实现将省略的复制/移动操作的源和目标视为引用同一对象的两种不同方式,并且该对象的销毁发生在如果不进行优化就会销毁这两个对象的晚些时候。复制/移动操作的简化,称为复制省略,允许在下列情况下(可合并以消除多份副本):

[...]

  • 当没有绑定到引用(12.2)的临时类对象被复制/移动到具有相同cv-非限定类型的类对象时

    ,可以通过将临时对象直接构造到省略的复制/移动的目标中来省略复制/移动操作。

考虑到所有这些,下面是表达式的结果A a = A(5):

  1. 编译器会看到带有复制初始化的声明。
  2. 这个

    A(int)

    构造函数以初始化临时对象。
  3. 因为临时对象是

    绑定到引用,并且它确实具有相同的类型。

    A

    作为复制初始化表达式中的目标类型,编译器可以直接将对象构造为

    a

    ,临时的


查看完整回答
反对 回复 2019-07-17
?
慕勒3428872

TA贡献1848条经验 获得超5个赞

A a = A(5);

这一行相当于

A a(5);

尽管它的功能样式外观,第一行简单地构造a与论点5。不涉及抄袭或临时人员。来自C+标准的第12.1.11节:

函数符号类型转换(5.2.3)可用于创建其类型的新对象。[注意:语法看起来像构造函数的显式调用。-尾注]


查看完整回答
反对 回复 2019-07-17
  • 3 回答
  • 0 关注
  • 313 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信