Return 2015 年 Visual Studio 价值优化?

Return value optimization in Visual Studio 2015?

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

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'

我不确定它以前为什么有效,但我假设由于 return 值优化调用了默认构造函数而不是复制构造函数。

我使用的代码是合法的C++吗?如果不是,那么在不需要我的 class C 的复制构造函数的情况下实现此代码的正确方法是什么?我当然可以使用移动构造函数,但我假设代码在 C++11 之前永远不会是有效的 C++?

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

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

With move constructor - 有效
Without move constructor - 无效,违反规则 5

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

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

因此您只需要自己定义移动构造函数,可能是一个 =default 构造函数。

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

If T is a class type, and the type of other is different, or if T is non-class type, but the type of other is a class type, user-defined conversion sequences that can convert from the type of other to T (or to a type derived from T if T is a class type and a conversion function is available) are examined and the best one is selected through overload resolution. The result of the conversion, which is a prvalue temporary if a converting constructor was used, is then used to direct-initialize the object. The last step is usually optimized out and the result of the conversion is constructed directly in the memory allocated for the target object, but the appropriate constructor (move or copy) is required to be accessible even though it's not used.