原子操作类
2026/7/1 12:20:10 网站建设 项目流程

C++11 对整型变量原子操作的支持

在 C++ 98/03 标准中,如果想对整型变量进行原子操作,要么利用操作系统提供的相关原子操作 API,要么利用对应操作系统提供的锁对象来对变量进行保护,无论是哪种方式,编写的代码都无法实现跨平台操作,例如上一小介绍的Interlocked系列 API 代码仅能运行于 Windows 系统,无法移植到 Linux 系统。C++ 11 新标准发布以后,改变了这种困境,新标准提供了对整型变量原子操作的相关库,即 std::atomic ,这是一个模板类型:

template<class T> struct atomic;

你可以传入具体的整型类型(如bool、char、short、int、uint等)对模板进行实例化,实际上 stl 库也提供了这些实例化的模板类型:

类型别名定义
std::atomic_boolstd::atomic<bool>
std::atomic_charstd::atomic<char>
std::atomic_scharstd::atomic<signed char>
std::atomic_ucharstd::atomic<unsigned char>
std::atomic_shortstd::atomic<short>
std::atomic_ushortstd::atomic<unsigned short>
std::atomic_intstd::atomic<int>
std::atomic_uintstd::atomic<unsigned int>
std::atomic_longstd::atomic<long>
std::atomic_ulongstd::atomic<unsigned long>
std::atomic_llongstd::atomic<long long>
std::atomic_ullongstd::atomic<unsigned long long>
std::atomic_char16_tstd::atomic<char16_t>
std::atomic_char32_tstd::atomic<char32_t>
std::atomic_wchar_tstd::atomic<wchar_t>
std::atomic_int8_tstd::atomic<std::int8_t>
std::atomic_uint8_tstd::atomic<std::uint8_t>
std::atomic_int16_tstd::atomic<std::int16_t>
std::atomic_uint16_tstd::atomic<std::uint16_t>
std::atomic_int32_tstd::atomic<std::int32_t>
std::atomic_uint32_tstd::atomic<std::uint32_t>
std::atomic_int64_tstd::atomic<std::int64_t>
std::atomic_uint64_tstd::atomic<std::uint64_t>

上表中仅列出了 C++11 支持的常用的整型原子变量,完整的列表读者可以参考这里:std::atomic - cppreference.com。

有了 C++ 语言本身对原子变量的支持以后,我们就可以“愉快地”写出跨平台的代码了,我们来看一段代码:

#include <atomic> #include <stdio.h> int main() { std::atomic<int> value; value = 99; printf("%d\n", (int)value); //自增1,原子操作 value++; printf("%d\n", (int)value); return 0; }

以上代码可以同时在 Windows 和 Linux 平台上运行,但是有读者可能会根据个人习惯将上述代码写成如下形式:

#include <atomic> #include <stdio.h> int main() { std::atomic<int> value = 99; printf("%d\n", (int)value); //自增1,原子操作 value++; printf("%d\n", (int)value); return 0; }

代码仅仅做了一点简单的改动,这段代码在 Windows 平台上运行良好,但是在 Linux 平台上会无法编译通过(这里指的是在支持 C++ 11语法的 g++ 编译中编译),提示错误是:

error: use of deleted function ‘std::atomic<int>::atomic(const std::atomic<int>&)’

产生这个错误的原因是 “std::atomic<int> value = 99;” 这一行代码调用的是 std::atomic 的拷贝构造函数,对于 int 型,其形式一般如下:

std::atomic<int>::atomic(const std::atomic<int>& rhs);

而根据 C++ 11 的规范,这个拷贝构造函数是默认使用=delete语法禁止编译器生成的,g++ 遵循了这个标准,参见这里 https://zh.cppreference.com/w/cpp/atomic/atomic/operator:

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

所以 Linux 平台上编译器会提示错误,而 Windows 的 VC++ 编译器没有遵循这个规范。而对于代码:

value = 99;

g++ 和 VC++ 同时实现规范中的:

T operator=( T desired )

因此,如果读者想利用 C++ 11 提供的 std::atomic 库编写跨平台的代码,在使用 std::atomic 提供的方法时建议参考官方 std::atomic 提供的接口说明来使用,而不是想当然地认为一个方法在此平台上可以运行,在另外一个平台也能有相同的行为,避免出现上面说的这种情形。

上述代码中之所以可以对 value 进行自增(++)操作是因为std::atomic类内部重载了operator =运算符,除此以外,std::atomic提供了大量有用的方法,这些方法您一定会觉得似曾相似:

方法名方法说明
operator=存储值于原子对象
store原子地以非原子对象替换原子对象的值
load原子地获得原子对象的值
exchange原子地替换原子对象的值并获得它先前持有的值
compare_exchange_weak
compare_exchange_strong
原子地比较原子对象与非原子参数的值,若相等则进行交换,若不相等则进行加载
fetch_add原子地将参数加到存储于原子对象的值,并返回先前保有的值
fetch_sub原子地从存储于原子对象的值减去参数,并获得先前保有的值
fetch_and原子地进行参数和原子对象的值的逐位与,并获得先前保有的值
fetch_or原子地进行参数和原子对象的值的逐位或,并获得先前保有的值
fetch_xor原子地进行参数和原子对象的值的逐位异或,并获得先前保有的值
operator++
operator++(int)
operator--
operator--(int)
令原子值增加或减少一
operator+=
operator-=
operator&=
operator|=
operator^=
=加、减,或与原子值进行逐位与、或、异或

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询