std::atomic<std::string> 是否正常工作?

Does std::atomic<std::string> work appropriately?

本文关键字:std 常工作 工作 gt atomic lt string 是否      更新时间:2023-10-16

我正在阅读Anthony Williams的《c++ Concurrency in Action》和第5章,其中讨论了新的多线程感知内存模型和原子操作,他说:

为了将std::atomic<UDT>用于某些用户定义的UDT,该类型必须有一个平凡的复制赋值操作符。

根据我的理解,这意味着如果以下返回true,我们可以使用std::atomic<UDT>:

std::is_trivially_copyable<UDT>::value

根据这个逻辑,我们不应该能够使用std::string作为std::atomic的模板参数并使其正常工作。

但是,以下代码编译并运行时会得到预期的输出:

#include <atomic>
#include <thread>
#include <iostream>
#include <string>
int main()
{
    std::atomic<std::string> atomicString;
    atomicString.store( "TestString1" );
    std::cout << atomicString.load() << std::endl;
    atomicString.store( "TestString2" );
    std::cout << atomicString.load() << std::endl;
    return 0;
}

这是一个未定义行为的情况,恰好按照预期的行为?

提前感谢!

该标准没有指定std::atomic<std::string>的专门化,因此应用通用的template <typename T> std::atomic<T>。29.5 [atomics.types。[通用]p1状态:

有一个泛型类模板原子。模板实参T的类型必须是可复制的(3.9)。

没有声明实现必须诊断是否违反此需求。所以要么(a)你对std::atomic<std::string>的使用调用了未定义的行为,要么(b)你的实现提供了std::atomic<std::string>作为一个符合标准的扩展。

查看std::atomic<T> (http://msdn.microsoft.com/en-us/library/vstudio/hh874651.aspx)的MSDN页面,它确实明确提到T是可复制的要求,并且它没有说任何关于std::atomic<std::string>的具体内容。如果它是一个扩展,它是未记录的。我把钱押在未定义的行为上。

具体来说,17.6.4.8/1适用(感谢Daniel krgler为我澄清):

在某些情况下(替换函数、处理函数、用于实例化标准库模板组件的类型操作),c++标准库依赖于c++程序提供的组件。如果这些组件不满足它们的要求,则本标准对实现没有任何要求。

std::string当然不满足std::atomic<T>的要求,即模板参数T是可复制的,因此该标准对实现没有要求。作为实现质量问题,请注意static_assert(std::is_trivially_copyable<T>::value, "std::atomic<T> requires T to be trivially copyable");是捕获此违规的简单诊断。


2016-04-19更新:我不知道什么时候发生了变化,但VS2015更新2现在诊断std::atomic<std::string>:

错误C2338: atomic要求T是可复制的。

不,这是未定义的行为。此外,由于std::string不是普通的可复制的,符合标准的编译器应该发出"至少一条诊断消息":

29.5原子类型

有一个泛型类模板原子。模板实参T的类型必须是可复制的(3.9)。

1.4实现遵从性

-如果程序违反了任何可诊断规则[…]一致的实现应发出至少一条诊断消息。