为什么不调用复制构造函数

Why the copy constructor is not called?

本文关键字:构造函数 复制 调用 为什么不      更新时间:2023-10-16

在此代码中:

#include <iostream>
using std::cout;
class Foo {
    public:
        Foo(): egg(0) {}
        Foo(const Foo& other): egg(1) {}
        int egg;
};
Foo bar() {
    Foo baz;
    baz.egg = 3;
    return baz;
}
int main(void) {
    Foo spam(bar());
    cout << spam.egg;
    return 0;
}

输出是3,而我期望它是1

这意味着在Foo spam(bar())行中没有调用复制构造函数。

我猜这是因为bar函数不返回引用。

你能解释一下spam初始化时到底发生了什么吗?

如果这是个愚蠢的问题,我先道歉。

谢谢!

复制/移动省略是所谓的"as-if"规则唯一允许的例外,该规则通常限制编译器允许在程序上执行的转换类型(例如优化)。

该规则旨在允许编译器执行他们希望的任何优化,只要转换后的程序"就像是原始程序一样"工作。然而,有一个重要的例外。

c++ 11标准第12.8/31段:

当满足某些条件时,允许实现省略类的复制/移动构造object, ,即使为复制/移动操作选择了构造函数和/或对象的析构函数有副作用。[…复制/移动操作的省略,称为复制省略,在以下情况下是允许的(其中可以组合以消除多个副本):

  • 出现在具有类返回类型的函数的return语句中,当表达式是类的名称时具有相同cv-不合格的非易失性自动对象(函数或catch子句参数除外)类型作为函数返回类型,则可以通过构造来省略复制/移动操作将自动对象直接转换为函数的返回值

[…]

  • ,当一个临时类对象没有被绑定到引用(12.2)时将被复制/移动对于具有相同cv- undefined类型的类对象,可以通过将临时对象直接构造为省略的copy/move
  • 的目标

[…]

换句话说,在12.8/31的规定适用的情况下,您永远不应该依赖于调用复制构造函数或移动构造函数,或者不调用