【C++学习笔记】 std::atomic 拷贝构造错误解析
std::atomic<int> flag_0x52 = 0;
以上代码报错如下:
public.cpp:55:18: Copying variable of type
'std::atomic<int>' invokes deleted constructor
xxatomic:200:2: 'atomic' has been explicitly marked deleted here
std::atomic<int> flag_0x52 = 0;
触发了 C++ 中 std::atomic
的拷贝构造函数被显式删除(deleted)的限制。以下是原因和解决方案:
错误原因
-
std::atomic
不可拷贝
std::atomic
的设计禁止拷贝构造和拷贝赋值(这些函数被标记为= delete
)。这是为了确保原子操作的独占性,避免意外复制破坏原子性。 -
初始化语法问题
代码使用了拷贝初始化(copy-initialization):std::atomic<int> flag_0x52 = 0; // 尝试调用拷贝构造函数(实际不可用)
虽然看起来是用
0
初始化,但编译器会尝试将其解释为std::atomic<int> temp(0); flag_0x52 = temp;
,进而触发拷贝操作。
解决方案
✅ 方法 1:使用直接初始化(推荐)
用圆括号 ()
替代等号 =
:
std::atomic<int> flag_0x52(0); // 正确:调用构造函数而非拷贝构造
✅ 方法 2:使用大括号初始化(C++11 起)
std::atomic<int> flag_0x52{0}; // 正确:列表初始化,不涉及拷贝
✅ 方法 3:分步初始化
std::atomic<int> flag_0x52; // 默认构造(值为0) // 或后续赋值flag_0x52 = 42; // 调用operator=,合法
关键原则
-
避免任何形式的拷贝:包括函数传参、返回值、容器操作等。需要传递时使用引用或指针。
-
初始化用
()
或{}
:确保直接调用构造函数而非触发拷贝。
错误示例修正
// 错误:尝试拷贝构造
std::atomic<int> a = 10; // ❌
std::atomic<int> b = a; // ❌ 显式拷贝
// 正确:直接构造
std::atomic<int> a(10); // ✅
std::atomic<int> b(a.load()); // ✅ 先读取值再构造(非拷贝原子对象本身)
提示:检查代码中其他可能涉及
std::atomic
复制的场景(如函数传参void foo(std::atomic<int>)
需改为void foo(std::atomic<int>&)
)。