在 msvs 2013 中 std::shared_ptr 的 compare_exchange_weak 是不是损坏?

Posted

技术标签:

【中文标题】在 msvs 2013 中 std::shared_ptr 的 compare_exchange_weak 是不是损坏?【英文标题】:is compare_exchange_weak for std::shared_ptr broken in msvs 2013?在 msvs 2013 中 std::shared_ptr 的 compare_exchange_weak 是否损坏? 【发布时间】:2013-12-27 17:48:17 【问题描述】:

请看样例

std::atomic < std::shared_ptr < int > > a;

std::shared_ptr < int > b;
std::shared_ptr < int > c = std::make_shared < int > (10);

while(a.compare_exchange_weak(b, c));

assert(a.load() == c);  
assert(a.load().use_count() == 2); // <- assertion is failed.

你怎么看?是编译器错误吗?

在 win32 模式下使用 msvs 2013 构建

【问题讨论】:

Herb Sutter 有一个针对 atomic_shared_ptr 的 C++(17?) 标准设计提案,该文档还解释了现有方法的缺点:open-std.org/jtc1/sc22/wg21/docs/论文/2014/n4162.pdf Спасибо, Максим, отличная статья Спасибо Гербу Саттеру ;-) 【参考方案1】:

您的程序表现出未定义的行为。

29.5/1 有一个通用类模板atomic&lt;T&gt;。模板参数 T 的类型应该是可简单复制的 (3.9)。

shared_ptr&lt;int&gt; 不可轻易复制。

【讨论】:

这个答案在 C++20 之前是正确的。有关它在 C++20 中如何更改的详细信息,请参阅此页面上的 this answer。【参考方案2】:

根据 Igor 的回答,std::atomic&lt;std::shared_ptr&lt;T&gt;&gt; 没有定义的行为。您需要使用 C++11 §20.7.2.5 shared_ptr 原子访问 [util.smartptr.shared.atomic] 中详述的 the non-member shared_ptr atomic function overloads。

std::shared_ptr < int > a;

std::shared_ptr < int > b;
std::shared_ptr < int > c = std::make_shared < int > (10);

while(std::atomic_compare_exchange_weak(&a, &b, c))
  ;

assert(std::atomic_load(&a) == c);  
assert(std::atomic_load(&a).use_count() == 2);

我觉得奇怪的是,该标准并未要求使用这些函数实现 template &lt;typename T&gt; struct std::atomic&lt;shared_ptr&lt;T&gt;&gt; 的部分特化。

我在Microsoft's documentation of the &lt;memory&gt; header 中没有看到非成员原子重载,因此它们可能不会在 VS2013 中实现。

【讨论】:

这个答案在 C++20 之前是正确的。有关它在 C++20 中如何更改的详细信息,请参阅此页面上的 this answer。【参考方案3】:

问题是关于 C++11,但值得指出的是,因为 C++20 OP 代码是有效的,因为 shared_ptr 和 @ 都有专门的 std::atomic 987654325@.

见:std::atomic&lt;std::shared_ptr&lt;T&gt;&gt; at cppreference

另外,使用std::atomic_compare_exchange 的替代方法是deprecated in C++20。

【讨论】:

以上是关于在 msvs 2013 中 std::shared_ptr 的 compare_exchange_weak 是不是损坏?的主要内容,如果未能解决你的问题,请参考以下文章

在 MSVS 2013 中使用 libtorrent

“预定义”和使用命名空间和 std::shared_ptr 的正确方法是啥?

一台计算机中的 msvs 2013 错误 C2057,另一台计算机中没有错误。这是怎么回事?

在 c++11 中转换 std::future 或 std::shared_future

为啥我不能在 C++0x 中对 std::shared_ptr 的向量执行 std::copy?

尝试调试 WCF 服务代码(MSVS 2013)时,在“添加监视”功能上获取“表达式评估器中的内部错误”