std::atomic<std::string> 是否正常工作?
Does std::atomic<std::string> work appropriately?
我正在阅读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实现遵从性-如果程序违反了任何可诊断规则[…]一致的实现应发出至少一条诊断消息。
- 为什么我的 std::ref 无法按预期工作?
- 为什么std::condition_variable notify_all的工作速度比notify_one快(对于随机请
- std::unique_ptr 在 GCC 中工作,但不能在 Visual Studio 中编译
- 如何创建一个类,以便向量工作 std::vector<MyClass<int>> v{ 1,2,3 };
- std::数组边界检查如何工作?
- C++ assigment std::list:<typename>:itrator 在 main 中工作,但在方法中它不起作用
- std::strlen 在内部是如何工作的?
- std::async 如何工作:为什么它会调用这么多次复制/移动?
- std::bind,无法让具有单个参数的方法工作
- 为什么"std::is_function_v"不能按预期工作?
- 不使用与左右停止工作命名空间 std 的简单比较
- 对 std::vector 的这种解读是如何工作的?
- std::notify_all_at_thread_exit 如何工作?
- boost::make_shared 失败,但 std::make_shared 工作
- 为什么STD ::计数将常数传递给Lambda,而不是在弦上工作时而不是字符
- 两个超载的STD ::前进工作如何
- 插入[n X n]矩阵类型的数据,并在运行时对其进行访问.将std::映射工作
- 右值模板参数隐式用作左值,并且 std::转发工作
- C++std::add_const工作不正常
- 为什么 <conio.h> 有时不起作用,并且在 C++ 中使用命名空间 std 可以工作