简体   繁体   English

Visual Studio 2013 和 2015 中的 C++ 编译器错误 C2280“试图引用已删除的函数”

[英]C++ Compiler Error C2280 "attempting to reference a deleted function" in Visual Studio 2013 and 2015

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?我错过了什么吗?

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).否则,它被定义为默认(8.4)。 The latter case is deprecated if the class has a user-declared copy assignment operator or a user-declared destructor.如果类具有用户声明的复制赋值运算符或用户声明的析构函数,则不推荐使用后一种情况。

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 .五法则

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”并在构造函数中赋值。

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 and use 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.请注意,如果您定义自定义移动构造函数,则还应该考虑赋值运算符和析构函数。

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.原来,我的一位班级成员(rapidjson 的 Document 对象)不允许复制。 Changed it to a reference, initialized via a *(new rapidjson::Document()) in the default ctor's initializer list.将其更改为引用,通过默认 ctor 的初始化列表中的 *(new rapidjson::Document()) 进行初始化。 Looks like all individual members should also be copy'able in addition to the defaulted copy ctor.看起来除了默认的复制构造函数之外,所有个人成员也应该是可复制的。

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.原因是在基类中使用了 std::atomic 成员变量。 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.查看我遇到的类似问题的其他很好的答案。

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 具有 std::atomic 成员变量的类的复制构造函数/赋值运算符出错

I encountered the same error, just because I had misused std::unique_ptr.我遇到了同样的错误,只是因为我误用了 std::unique_ptr。

Note that std::unique_ptr is non-copyable , it is only moveable.请注意 std::unique_ptr 是不可复制的,它只能移动。

Here is the wrong demonstration.这是错误的示范。

class word;
class sentence
{
    public:
        sentence();
        ~sentence();

    public:
        // Wrong demonstration, because I pass the parameter by value/copying
        // I should use 'std::shared_ptr< word >' instead.
        sentence(std::initializer_list< std::unique_ptr< word > > sentence);
};

The following code is taken from MSVC compiler's STL library.以下代码取自 MSVC 编译器的 STL 库。 We can see that the copy constructor and copy assignment operator of class unique_ptr are deleted explicitly.我们可以看到,类 unique_ptr 的复制构造函数和复制赋值运算符显式删除

    unique_ptr(const unique_ptr&) = delete;
    unique_ptr& operator=(const unique_ptr&) = delete;

I faced this issue today and mine was caused by having both std::stringstream and std::ostream as member variables.我今天遇到了这个问题,我的问题是由std::stringstreamstd::ostream作为成员变量引起的。 I initially thought this was caused because I accidentally named one of them as sstream which was the name for the header file <sstreamn> I had included previously.我最初认为这是因为我不小心将其中一个命名为sstream ,这是我之前包含的头文件<sstreamn>的名称。

But changing the name didn't help, and I had to remove the ostream variable completely for this to work again!但是更改名称没有帮助,我必须完全删除ostream变量才能使其再次工作! then I realized I had declared it incorrectly like this:然后我意识到我像这样错误地声明了它:

std::ostream some_stream;

while it should have been :虽然它应该是:

...
std::ostream some_stream(&filebuf);

Basically, I was much better off using ofstream instead!基本上,我最好使用ofstream代替!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 编译器错误C2280,尝试引用已删除的函数operator = - Compiler error C2280, attempting to reference a deleted function operator= C ++错误C2280:尝试引用已删除的函数 - C++ Error C2280: Attempting to reference a deleted function C2280尝试引用已删除的功能 - C2280 attempting to reference a deleted function C2280 = 试图引用已删除的 function - C2280 = attempting to reference a deleted function 错误C2280:尝试引用已删除的功能 - error C2280: attempting to reference a deleted function Qt编译错误:C2280:尝试引用已删除的函数 - Qt compile error: C2280: attempting to reference a deleted function 错误C2280:尝试引用已删除的函数(原子 <int> ) - error C2280: attempting to reference a deleted function (atomic<int>) 错误C2280:在声明C ++结构时尝试引用已删除的函数 - error C2280: attempting to reference a deleted function while declaring a C++ struct C++ 错误 C2280 - 尝试引用已删除的 Function - 在原始类型上 - C++ Error C2280 - Attempting to Reference a Deleted Function - On Primitive Types C++:带有 const int 的 class 的 vector.erase 实例给出“试图引用已删除的函数”错误 C2280 - C++: vector.erase instance of a class with const int gives "attempting to reference a deleted function" error C2280
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM