错误 C2280:尝试引用已删除的函数(原子<int>)

error C2280: attempting to reference a deleted function (atomic<int>)

本文关键字:原子 lt int 函数 gt C2280 引用 删除 错误      更新时间:2023-10-16

我有一个class A,其成员变量_atomicVar类型为std::atomic<int>

#include <atomic>
class A
{
public:
    A();
    ~A();
private:
    std::atomic<int> _atomicVar;
};

如果我构建项目,我会得到以下错误:

error C2280: 'std::atomic<int>::atomic(const std::atomic<int> &)' : attempting to reference a deleted function

我主要是一名C#开发人员,所以我还不了解C++的每一个细节。我不知道我在哪里使用atomic<int>的副本
我还尝试初始化_atomicVar:

std::atomic<int> _atomicVar { 0 };

但那没用
我希望_atomicVar(没有显式初始化)将使用int的默认值进行初始化
你能告诉我为什么会出现这个错误吗?

这是因为std::atomic的复制构造函数被删除了。

请参阅本文档页。

由于并没有为A定义显式复制构造函数,编译器会生成默认的复制构造函数,它只是为所有成员调用复制构造函数(这对于std::atomic是不允许的)。

解决方案:

class A
{
public:
    A();
    A(const A& origin); // add this line
    ~A();
private:
    std::atomic<int> _atomicVar;
};
A::A(const A& origin)
: _atomicVar(0) //zero-initialize _atomicVar
{
}

编辑

如果您想知道为什么atomic类型不可复制,您可能想阅读这个问题,特别是公认的答案。如果你想复制std::atomic的值,你可以这样做:

A::A(const A& origin)
: _atomicVar(origin._atomicVar.load())
{
}

但请记住,这个操作本身不会是原子操作(而且,对于大多数逻辑来说,毫无意义)。

此外,您可能还想定义显式赋值运算符(记住"三条规则")。

程序正确运行的最佳选择是删除以下两种方法:

class A
{
public:
    A();
    A(const A&) = delete;
    ~A();
    A& operator=(const A&) = delete;
private:
    std::atomic<int> _atomicVar;
};

如果您的编译器不支持此功能(例如,VC12之前的任何VC),请将它们声明为私有,并且不提供正文:

class A
{
public:
    A();
    ~A();
private:
    //do not define these two
    A(const A&);
    A& operator=(const A&);
private:
    std::atomic<int> _atomicVar;
};