我正在阅读 Anthony Williams 的《C++ Concurrency in Action》第 5 章,其中讨论了新的多线程感知内存模型和原子操作,他指出:
为了使用std::atomic<UDT>
对于一些用户定义的UDT
,该类型必须有一个trivial复制赋值运算符。
据我了解,这意味着我们可以使用std::atomic<UDT>
如果以下返回 true:
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.generic] p1 指出:
有一个通用类模板原子。模板参数 T 的类型应该是可简单复制的(3.9)。
没有声明实施必须诊断违反此要求的情况。所以(a)你使用std::atomic<std::string>
调用未定义的行为,或者 (b) 您的实现提供std::atomic<std::string>
作为一致的扩展。
查看 MSDN 页面std::atomic<T>
(http://msdn.microsoft.com/en-us/library/vstudio/hh874651.aspx http://msdn.microsoft.com/en-us/library/vstudio/hh874651.aspx),它确实明确提到了这样的要求:T
可以简单地复制,并且它没有说明任何具体内容std::atomic<std::string>
。如果它是扩展,则它是未记录的。我的钱花在未定义的行为上。
具体来说,17.6.4.8/1 适用(感谢 Daniel Krügler 让我改正过来 https://groups.google.com/a/isocpp.org/d/msg/std-discussion/YEB0sIgGoHA/PL4NYEq5yykJ):
在某些情况下(替换函数、处理函数、用于实例化标准库模板组件的类型的操作),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 Update 2 现在可以诊断std::atomic<std::string>
:
error C2338: atomic requires T to be trivially copyable.
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)