为什么线程清理程序会抱怨这个std::ranges::views::filter代码



运行此代码时,线程清理程序会抱怨数据争用。为什么?

#include <iostream>
#include <ranges>
#include <thread>
#include <vector>
int main(){
std::vector v{11,22,33,44,55,66};
auto view = v | std::ranges::views::filter([](const auto x){
return x>47;
});
std::jthread jt1([&]{
int sum =0;
for (const auto& val: view) {sum+=val;}
});    
std::jthread jt2([&]{
int sum =0;
for (const auto& val: view) {sum+=val;}
});
}

注意:我知道这个问题的答案,我最近在看一个演讲时学会了,但我发现它非常令人惊讶,而且没有与此相关的问题,所以我想分享它。如果没有人有兴趣回答,我会自己回答。

运行lambda的线程中的[&]应该立即发出警报。通过非const引用将随机对象传递给线程通常是不安全的。特别是,在标准库对象上调用非const成员函数不是线程安全的。

begin不是std::ranges::filter_viewconst成员函数。

constexpr iterator begin();
预期:pred_.has_value()
返回:{*this, ranges::find_if(base_, ref(*pred_))}
备注:为了提供范围概念所需的摊余常数时间复杂性,此函数将结果缓存在CCD_ 10中以用于后续调用。

在libstdc++实现中,正是这种缓存操作触发了线程清理程序。

试图使view恒定会导致编译错误。

reverse_view也是如此。

其他范围适配器确实有beginconst过载。

通过在构造线程之前调用view.begin(),可以在实践中解决这个问题。我不知道这是否会让未定义的行为正式消失(我认为可能应该(,但它确实会让消毒液静音。

相关内容

  • 没有找到相关文章

最新更新