返回值优化是否需要声明复制构造函数

Ins*_*oop 5 c++ rvo

我发现英特尔编译器不会为std :: array对象生成返回值优化.以下代码恰好位于我的程序的内部循环中,并未进行优化.

std::array<double, 45> f(const std::array<double, 45>& y) {
    auto dy_dt = std::array<double, 45>( );
    ...

    return dy_dt;
}
Run Code Online (Sandbox Code Playgroud)

我已经发现这种行为来自于我的标准库实现没有为std :: array显式定义复制构造函数的事实.以下代码演示了:

class Test {
public:
    Test() = default;
    Test(const Test& x);
};

Test f() {
    auto x = Test( );

    return x;
}
Run Code Online (Sandbox Code Playgroud)

用它编译时

icpc -c -std=c++11 -qopt-report=2 test.cpp -o test.o
Run Code Online (Sandbox Code Playgroud)

报告文件显示

INLINE REPORT: (f(Test *)) [1] main.cpp(7,10)
Run Code Online (Sandbox Code Playgroud)

这证明了编译器生成了RVO(f的签名被更改,因此它可以将新创建​​的对象放在调用站点的堆栈上).但是,如果您注释掉声明的行Test(const Test& x);,则报告文件会显示

INLINE REPORT: (f()) [1] main.cpp(7,10)
Run Code Online (Sandbox Code Playgroud)

这证明RVO没有生成.

在定义RVO的C++ 11标准的12.8.31中,他们给出的示例有一个复制构造函数.那么,这是英特尔编译器的"错误"还是符合标准的实现?

M.M*_*M.M 1

由于违反了“单一定义规则”,该程序会导致未定义的行为,无需进行诊断。

当按值返回时,复制构造函数会被 odr 使用——即使发生了复制省略

odr 使用的非内联函数意味着该函数的一个定义必须出现在程序中。但是,您没有提供任何内容,并且您的复制构造函数声明会抑制编译器生成的定义。