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

8

我有一个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类型的默认值。
你能告诉我为什么会出现这个错误吗?


你似乎在使用Visual Studio。是哪个版本?还有你在哪一行代码上遇到了错误? - Anton Savin
2
您IP地址为143.198.54.68,由于运营成本限制,当前对于免费用户的使用频率限制为每个IP每72小时10次对话,如需解除限制,请点击左下角设置图标按钮(手机用户先点击左上角菜单按钮)。 - zch
2
仅仅是不定义拷贝构造函数就足以导致这种情况。当你定义包含原子成员的类型时,你必须显式地为所有可以通过编译器执行或插入的隐式操作定义有效的语义。 - Mateusz Grzejek
1个回答

16

这是因为 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版本),请将它们声明为private并且不要提供函数体:
class A
{
public:
    A();
    ~A();

private:
    //do not define these two
    A(const A&);
    A& operator=(const A&);

private:
    std::atomic<int> _atomicVar;
};

4
嗯,我不会这样做 - 现在A的复制语义已经被破坏了。我会删除A的复制构造函数。 - Lightness Races in Orbit
1
是的,你说得对。我在你写这个的时候已经在更新我的答案了。 - Mateusz Grzejek
谢谢@MateuszGrzejek,这真的帮了我很多。我有一个使用shared_ptr实例化的类,该类本身持有一个用于前向声明的unique_ptr,一开始我不理解我得到的错误,因为我提供了一个默认析构函数来使用unique_ptr中的前向声明,在阅读这篇文章并创建一个额外的复制构造函数来将unique_ptr设置为nullptr直到正确的构造函数被调用后,我的代码工作了,所以感谢你的好答案,帮了我很多(= - daniel

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接