Visual Studio 2015中的返回值优化?

fsc*_*enm 10 c++ visual-studio visual-c++ visual-studio-2015

在一个probject中我使用了类似于以下的代码:

class C {
public:
    C() {}

    C(const C&) = delete;
};

C f() {
    return C();
}

int main() {
    f();
}
Run Code Online (Sandbox Code Playgroud)

在我之前使用的每个Visual C++编译器中(直到2013年),这从来都不是问题.但是当我尝试使用新的Visual C++ 2015编译器编译它时,我收到以下错误:

1>c:\devel\c++11\playground\main.cpp(10): error C2280: 'C::C(const C &)': attempting to reference a deleted function
1>  c:\devel\c++11\playground\main.cpp(6): note: see declaration of 'C::C'
Run Code Online (Sandbox Code Playgroud)

我不确定它为什么以前有效,但我认为由于返回值优化,默认构造函数被调用而不是复制构造函数.

我使用的代码甚至是合法的C++吗?如果没有,那么在不需要我的类的复制构造函数的情况下实现此代码的正确方法是C什么?我当然可以使用移动构造函数但是我认为代码在C++ 11之前从来就不是有效的C++?

Max*_*kin 9

使用复制初始化初始化函数参数和返回值.复制初始化要求可以访问复制构造函数,即使它们被(N)RVO省略:

如果T是类类型,并且其他类型不同,或者T是非类型类型,但是其他类型是类类型,则用户定义的转换序列可以从其他类型转换为T(或检查从T派生的类型(如果T是类类型并且转换函数可用),并且通过重载决策选择最佳的类型.转换的结果(如果使用转换构造函数,则是prvalue临时值)然后用于直接初始化对象.最后一步通常是优化的,转换的结果直接在为目标对象分配的内存中构造,但是即使没有使用,也需要访问适当的构造函数(移动或复制).

  • Visual Studio从未成为遵循C++标准的典范. (8认同)
  • @fschoenm不,之前的行为完全合法 - 您声明了复制构造函数,因此它是可访问的:使用它的return语句不会导致错误.由于编译器应用了RVO,因此实际上并没有调用构造函数,因此您没有提供实现的事实并不重要.现在你宣布复制构造=删除,它不再可访问,因此错误. (4认同)

Cor*_*mer 7

你需要遵循5规则.由于您删除了复制构造函数,因此需要定义移动构造函数.

C(C&&) = default;
C& operator=(C&&) = default;
Run Code Online (Sandbox Code Playgroud)

使用移动构造函数 - 工作
没有移动构造函数 - 不起作用,违反了规则5

注意上面的站点使用gcc甚至它不会编译,因此它不是特定于Visual Studio,这是一个已定义和预期的行为.