Visual Studio 2013 和 2015 中的 C++ 编译器错误 C2280“试图引用已删除的函数”
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/31264984/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
C++ Compiler Error C2280 "attempting to reference a deleted function" in Visual Studio 2013 and 2015
提问by Alessandro Jacopson
This snippet is compiled without errors in Visual Studio 2013 (Version 12.0.31101.00 Update 4)
此代码段在 Visual Studio 2013(版本 12.0.31101.00 更新 4)中编译时没有错误
class A
{
public:
A(){}
A(A &&){}
};
int main(int, char*)
{
A a;
new A(a);
return 0;
}
while it is compiled with this error in Visual Studio 2015 RC (Version 14.0.22823.1 D14REL):
在 Visual Studio 2015 RC(版本 14.0.22823.1 D14REL)中编译时出现此错误:
1>------ Build started: Project: foo, Configuration: Debug Win32 ------
1> foo.cpp
1>c:\dev\foo\foo.cpp(11): error C2280: 'A::A(const A &)': attempting to reference a deleted function
1> c:\dev\foo\foo.cpp(6): note: compiler has generated 'A::A' here
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
I think that the compiler shipped with Visual Studio 2015 generates the Copy Constructor and marks it as =delete
and so I get the error C2280 (which, by the way, I cannot find documented on msdn.microsoft.com).
我认为 Visual Studio 2015 附带的编译器生成复制构造函数并将其标记为=delete
,因此我收到错误 C2280(顺便说一下,我在 msdn.microsoft.com 上找不到该错误)。
Now, let's say I have a codebase which is compilable with Visual Studio 2013 (and it works because it relies on the code generated automatically by the compiler) but not compilable with Visual Studio 2015 due to C2280, how can I fix the problem?
现在,假设我有一个可以用 Visual Studio 2013 编译的代码库(它可以工作,因为它依赖于编译器自动生成的代码)但由于 C2280 而不能用 Visual Studio 2015 编译,我该如何解决这个问题?
I was thinking to declare class A
in this way:
我想以A
这种方式声明类:
class A
{
public:
A(){}
A(A &&){}
A(const A&)=default;
};
am I missing something?
我错过了什么吗?
回答by Barry
From [class.copy]/7, emphasis mine:
来自 [class.copy]/7,强调我的:
If the class definition does not explicitly declare a copy constructor, a non-explicit one is declared implicitly. If the class definition declares a move constructor or move assignment operator, the implicitly declared copy constructor is defined as deleted; otherwise, it is defined as defaulted (8.4). The latter case is deprecated if the class has a user-declared copy assignment operator or a user-declared destructor.
如果类定义未显式声明复制构造函数,则隐式声明非显式构造函数。 如果类定义声明了移动构造函数或移动赋值运算符,则隐式声明的复制构造函数定义为删除;否则,它被定义为默认(8.4)。如果类具有用户声明的复制赋值运算符或用户声明的析构函数,则不推荐使用后一种情况。
There is an equivalent section with similar wording for copy assignment in paragraph 18. So your class is really:
在第 18 段中有一个具有相似措辞的副本分配的等效部分。所以你的班级实际上是:
class A
{
public:
// explicit
A(){}
A(A &&){}
// implicit
A(const A&) = delete;
A& operator=(const A&) = delete;
};
which is why you can't copy-construct it. If you provide a move constructor/assignment, and you still want the class to be copyable, you will have to explicitly provide those special member functions:
这就是为什么你不能复制构造它。如果您提供移动构造函数/赋值,并且您仍然希望该类是可复制的,则必须显式提供这些特殊成员函数:
A(const A&) = default;
A& operator=(const A&) = default;
You will also need to declare a move assignment operator. If you really have a need for these special functions, you will also probably need the destructor. See Rule of Five.
您还需要声明一个移动赋值运算符。如果您真的需要这些特殊功能,您可能还需要析构函数。见五法则。
回答by doby
I had the same problem and it was due to a poorly defined member variable:
我遇到了同样的问题,这是由于成员变量定义不明确:
double const deltaBase = .001;
Putting this in will cause the copy constructor to be deleted. Get rid of the "const" and assign in the constructor.
将其放入将导致复制构造函数被删除。摆脱“const”并在构造函数中赋值。
回答by TartanLlama
If you write a user-defined move constructor for your class, the copy constructor will be deleted. This is because if a class needs special behaviour for its move constructor, it probably needs some similar behaviour in its copy constructor, so the copy constructor will be deleted to stop you from inadvertently using the default behaviour.
如果为类编写用户定义的移动构造函数,则复制构造函数将被删除。这是因为如果一个类的移动构造函数需要特殊的行为,它的复制构造函数可能需要一些类似的行为,所以复制构造函数将被删除,以防止您无意中使用默认行为。
If you want to define your own move constructor anduse the default copy constructor, you need to declare it as default
, like you suggested in your question:
如果您想定义自己的移动构造函数并使用默认的复制构造函数,则需要将其声明为default
,就像您在问题中建议的那样:
class A
{
public:
A(){}
A(A &&){}
//I know what I'm doing, compiler, use the default version.
A(const A&)=default;
};
Note that if you define a custom move constructor, you should think about your assignment operators and destructor as well.
请注意,如果您定义自定义移动构造函数,则还应该考虑赋值运算符和析构函数。
回答by n-mam
I was stuck with this error even after "default"ing the copy ctor. Turned out, one of my class member (rapidjson's Document object) was disallowing copy. Changed it to a reference, initialized via a *(new rapidjson::Document()) in the default ctor's initializer list. Looks like all individual members should also be copy'able in addition to the defaulted copy ctor.
即使在“默认”复制构造函数之后,我也遇到了这个错误。原来,我的一位班级成员(rapidjson 的 Document 对象)不允许复制。将其更改为引用,通过默认 ctor 的初始化列表中的 *(new rapidjson::Document()) 进行初始化。看起来除了默认的复制构造函数之外,所有个人成员也应该是可复制的。
回答by piyu2cool
I ran into a similar situation where I had a hierarchy of classes and a destructor in the base class was declared virtual. In this case, compiler does NOT automatically generate move and copy constructors. So we have to default these in order for compiler to generate the definitions for these methods.
我遇到了类似的情况,我有一个类层次结构,基类中的析构函数被声明为虚拟的。在这种情况下,编译器不会自动生成移动和复制构造函数。所以我们必须默认这些,以便编译器为这些方法生成定义。
However, I ran into another issue after I defaulted copy and move constructor. I saw that the compiler was still not able to generate copy and move constructors. The reason was the usage of std::atomic member variable in the base class. Since atomic variable are not copy able or movable, the compiler could not generate definitions for copy constructor. This gave me lot of headache and I had to solve the problem using a different method. See other great answers for similar issue that I faced.
但是,在默认复制和移动构造函数后,我遇到了另一个问题。我看到编译器仍然无法生成复制和移动构造函数。原因是在基类中使用了 std::atomic 成员变量。由于原子变量不可复制或可移动,编译器无法为复制构造函数生成定义。这让我很头疼,我不得不使用不同的方法来解决这个问题。查看我遇到的类似问题的其他很好的答案。
References: Does a default virtual destructor prevent compiler-generated move operations?
Error with copy constructor/assignment operator for a class which has std::atomic member variable