Visual Studio 2015中的返回值优化?

时间:2015-07-21 12:54:29

标签: c++ visual-studio visual-c++ visual-studio-2015

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

class C {
public:
    C() {}

    C(const C&) = delete;
};

C f() {
    return C();
}

int main() {
    f();
}

在我之前使用的每个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'

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

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

3 个答案:

答案 0 :(得分:9)

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

  

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

答案 1 :(得分:7)

您需要关注rule of 5。由于您删除了复制构造函数,因此需要定义移动构造函数。

C(C&&) = default;
C& operator=(C&&) = default;

With move constructor - 作品
Without move constructor - 不起作用,违反了5条规则

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

答案 2 :(得分:0)

也许之前它设法为此选择了隐式生成的移动构造函数,但是在VS 2015中,复制操作的存在阻止了隐式生成移动构造函数,如果我没记错的话,这是符合标准的行为。

所以你只需要自己定义移动构造函数,可能是a = default。