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

Posted

技术标签:

【中文标题】Visual Studio 2013 和 2015 中的 C++ 编译器错误 C2280“试图引用已删除的函数”【英文标题】:C++ Compiler Error C2280 "attempting to reference a deleted function" in Visual Studio 2013 and 2015 【发布时间】:2015-09-24 17:30:26 【问题描述】:

此 sn-p 在 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;

在 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 ==========

我认为 Visual Studio 2015 附带的编译器会生成复制构造函数并将其标记为 =delete,因此我收到错误 C2280(顺便说一句,我在 msdn.microsoft.com 上找不到文档)。

现在,假设我有一个可与 Visual Studio 2013 编译的代码库(它可以工作,因为它依赖于编译器自动生成的代码)但由于 C2280 而不能与 Visual Studio 2015 编译,我该如何修复有问题吗?

我正在考虑以这种方式声明类A

class A

public:
   A()
   A(A &&)
   A(const A&)=default;
;

我错过了什么吗?

【问题讨论】:

还有A& operator=(A&&) ;A& operator=(const A&); 在我的例子中,我的类中有一个 std::unique_ptr 阻止编译器生成隐式复制构造函数。 【参考方案1】:

来自 [class.copy]/7,强调我的:

如果类定义没有显式声明复制构造函数,则隐式声明非显式构造函数。 如果类定义声明了移动构造函数或移动赋值运算符,则隐式声明的副本 构造函数被定义为删除;否则,它被定义为默认值(8.4)。如果后一种情况不推荐使用 该类具有用户声明的复制赋值运算符或用户声明的析构函数。

第 18 段中有一个类似的部分,用于复制作业。所以你的班级真的是:

class A

public:
   // explicit
   A()
   A(A &&)

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

这就是你不能复制构建它的原因。如果你提供了一个移动构造函数/赋值,并且你仍然希望类是可复制的,你将不得不显式地提供那些特殊的成员函数:

    A(const A&) = default;
    A& operator=(const A&) = default;

您还需要声明一个移动赋值运算符。如果您真的需要这些特殊功能,您可能还需要析构函数。见Rule of Five。

【讨论】:

【参考方案2】:

我遇到了同样的问题,这是由于定义不明确的成员变量:

double const deltaBase = .001;

把这个放进去会导致拷贝构造函数被删除。摆脱“const”并在构造函数中赋值。

【讨论】:

这里相同,但我有一个未设置的引用并遇到了这个问题:Foo& foo; 我的类中有一个 ostringstream 对象导致了这个错误。 我也遇到了这个错误,但我仍然不明白为什么 const 会导致复制构造函数被删除。【参考方案3】:

即使在“默认”复制 ctor 之后,我仍然遇到此错误。原来,我的一个班级成员(rapidjson 的 Document 对象)不允许复制。将其更改为引用,通过默认 ctor 的初始化列表中的 *(new rapidjson::Document()) 进行初始化。看起来除了默认的复制 ctor 之外,所有个人成员也应该是可复制的。

【讨论】:

【参考方案4】:

如果你为你的类编写一个用户定义的移动构造函数,复制构造函数将被删除。这是因为如果一个类的移动构造函数需要特殊行为,它的复制构造函数中可能需要一些类似的行为,所以复制构造函数将被删除以防止您无意中使用默认行为。

如果您想定义自己的移动构造函数使用默认的复制构造函数,则需要将其声明为default,就像您在问题中建议的那样:

class A

public:
   A()
   A(A &&)
   //I know what I'm doing, compiler, use the default version.
   A(const A&)=default;
;

请注意,如果您定义了自定义移动构造函数,则还应考虑赋值运算符和析构函数。

【讨论】:

在 C++14 中是否仍然存在编译器可以选择复制构造函数的情况,还是编译器不会选择复制构造函数而是因为没有可用的构造函数而失败?我想我读到这会改变,但忘记了它是否在 C++14 中。【参考方案5】:

我遇到了类似的情况,我有一个类层次结构,并且基类中的析构函数被声明为虚拟的。在这种情况下,编译器不会自动生成移动和复制构造函数。所以我们必须默认这些,以便编译器生成这些方法的定义。

但是,在我默认复制和移动构造函数后,我遇到了另一个问题。我看到编译器仍然无法生成复制和移动构造函数。原因是在基类中使用了 std::atomic 成员变量。由于原子变量不可复制或不可移动,编译器无法为复制构造函数生成定义。这让我很头疼,我不得不用不同的方法解决这个问题。 对于我遇到的类似问题,请查看其他很好的答案。

参考资料: 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

【讨论】:

【参考方案6】:

我遇到了同样的错误,只是因为我误用了 std::unique_ptr。

注意 std::unique_ptr 不可复制,它只能移动。

这是错误的演示。

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);
;

以下代码取自 MSVC 编译器的 STL 库。我们可以看到unique_ptr类的拷贝构造函数和拷贝赋值运算符被显式删除

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

【讨论】:

【参考方案7】:

我今天遇到了这个问题,我的问题是由 std::stringstreamstd::ostream 作为成员变量引起的。我最初认为这是因为我不小心将其中一个命名为 sstream,这是我之前包含的头文件 &lt;sstreamn&gt; 的名称。

但是更改名称并没有帮助,我必须完全删除 ostream 变量才能再次工作!然后我意识到我这样声明它是错误的:

std::ostream some_stream;

虽然它应该是:

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

基本上,我最好改用ofstream

【讨论】:

以上是关于Visual Studio 2013 和 2015 中的 C++ 编译器错误 C2280“试图引用已删除的函数”的主要内容,如果未能解决你的问题,请参考以下文章

使用Visual Studio2013打开Visual Studio2015项目

Intel parallel studio 2017 集成在visual studio 2013 中,现在如何集成到visual studio 2015

Visual Studio 2015/2013安装失败:Microsoft Visual Studio 2015 Shell (Minimum) Interop Assemblies 安装时发生严重错

锁定 Windows 8.1 时 Visual Studio 2013 和 2015 崩溃

Visual Studio 2013/2015 包管理器控制台未初始化

使用平台工具集 v120 (Visual Studio 2013) 在 Visual Studio 2015 中创建 C++/CLI 项目