Visual Studio 2015中的返回值优化

Return value optimization in Visual Studio 2015?

本文关键字:返回值 优化 Studio 2015 Visual      更新时间:2023-10-16

在一个项目中,我使用了如下代码:

class C {
public:
    C() {}
    C(const C&) = delete;
};
C f() {
    return C();
}
int main() {
    f();
}

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

1>c:develc++11playgroundmain.cpp(10): error C2280: 'C::C(const C &)': attempting to reference a deleted function
1>  c:develc++11playgroundmain.cpp(6): note: see declaration of 'C::C'

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

我使用的代码是合法的c++吗?如果不是,实现这段代码的正确方法是什么,而不需要为我的类C提供复制构造函数?我当然可以使用移动构造函数但我假设代码在c++ 11之前永远都是无效的?

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

省略

如果T是类类型,而other的类型不同,或者如果T不是类类型,但other的类型是类类型,则检查用户定义的转换序列,该序列可以从other的类型转换为T(或者如果T是类类型并且有转换函数,则转换为T派生的类型),并通过重载解析选择最佳转换序列。转换的结果(如果使用转换构造函数,则是一个右值临时值)随后用于直接初始化对象。最后一步通常被优化掉,转换的结果直接在为目标对象分配的内存中构造,但是需要适当的构造函数(move或copy)即使不使用也可以访问。

你需要遵循5原则。由于删除了复制构造函数,因此需要定义move构造函数。

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

With move constructor - works
没有移动构造函数-不起作用,违反了5

规则

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

也许以前它成功地选择了隐式生成的移动构造函数,但在VS 2015中,隐式生成的移动构造函数被复制操作的存在所阻塞,如果我记得正确的话,这是符合标准的行为。

所以你只需要自己定义move构造函数,可能是一个=default。