C ++编译器错误C2280“试图引用已删除的函数”在Visual Studio 2013和2015中 [英] C++ Compiler Error C2280 "attempting to reference a deleted function" in Visual Studio 2013 and 2015

查看:451
本文介绍了C ++编译器错误C2280“试图引用已删除的函数”在Visual Studio 2013和2015中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

此代码段在Visual Studio 2013(版本12.0.31101.00更新4)中编译无误

This snippet is compiled without errors in Visual Studio 2013 (Version 12.0.31101.00 Update 4)

class A
{
public:
   A(){}
   A(A &&){}
};

int main(int, char*)
{
   A a;
   new A(a);
   return 0;
}

,而在Visual Studio 2015 RC(版本14.0中,此错误编译时)。 22823.1 D14REL):

while it is compiled with this error in Visual Studio 2015 RC (Version 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认为Visual Studio 2015附带的编译器会生成Copy构造函数并将其标记为 = delete ,因此我收到错误C2280(顺便说一下,我找不到记录

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 2013一起编译的代码库(之所以起作用,是因为它依赖于自动生成的代码)

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?

我当时想声明类 A,但由于C2280无法在Visual Studio 2015中编译,该如何解决该问题? 这样:

class A
{
public:
   A(){}
   A(A &&){}
   A(const A&)=default;
};

我错过了什么吗?

推荐答案

从[class.copy] / 7中着重强调:

From [class.copy]/7, emphasis mine:


如果类定义未明确声明一个副本构造函数,一个非显式的隐式声明。
如果类定义声明了move构造函数或move赋值运算符,则隐式声明的副本
构造函数定义为Deleted
;否则,将其定义为默认值(8.4)。如果
类具有用户声明的副本分配运算符或用户声明的析构函数,则不建议使用后者。

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.

在第18段中,有一个等价的部分,用类似的措词来指代副本分配。因此,您的课程确实是:

There is an equivalent section with similar wording for copy assignment in paragraph 18. So your class is really:

class A
{
public:
   // explicit
   A(){}
   A(A &&){}

   // implicit
   A(const A&) = delete;
   A& operator=(const A&) = delete;
};

这就是为什么您不能复制构造它的原因。如果提供了move构造函数/赋值,但仍希望该类是可复制的,则必须显式提供那些特殊的成员函数:

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.

这篇关于C ++编译器错误C2280“试图引用已删除的函数”在Visual Studio 2013和2015中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆