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

Tor*_*enJ 7 c++ c++11 stdatomic

我有一个类型class A的成员变量._atomicVarstd::atomic<int>

#include <atomic>

class A
{
public:
    A();
    ~A();

private:
    std::atomic<int> _atomicVar;
};
Run Code Online (Sandbox Code Playgroud)

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

error C2280: 'std::atomic<int>::atomic(const std::atomic<int> &)' : attempting to reference a deleted function
Run Code Online (Sandbox Code Playgroud)

我主要是一名C#开发人员,所以我还不知道C++的每一个细节.我不知道我在哪里使用复制文件atomic<int>.
我也尝试初始化_atomicVar:

std::atomic<int> _atomicVar { 0 };
Run Code Online (Sandbox Code Playgroud)

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

Mat*_*jek 15

那是因为复制构造函数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
{
}
Run Code Online (Sandbox Code Playgroud)

编辑

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

A::A(const A& origin)
: _atomicVar(origin._atomicVar.load())
{
}
Run Code Online (Sandbox Code Playgroud)

但请记住,这个操作本身不会是原子操作(对于大多数逻辑来说,没有意义).

此外,您可能还需要定义显式赋值运算符(请记住关于Rule of Three).

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

class A
{
public:
    A();
    A(const A&) = delete;
    ~A();

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

private:
    std::atomic<int> _atomicVar;
};
Run Code Online (Sandbox Code Playgroud)

如果您的编译器不支持此功能(例如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;
};
Run Code Online (Sandbox Code Playgroud)

  • 嗯我不会这样做 - 现在`A`的复制语义被破坏了.我会改为`删除``A`的复制构造函数. (3认同)