在一个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 ++?
答案 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。