gpt4 book ai didi

c++ - 从 std::deque 线程安全地同时调用 emplace_back() 和 operator[]() 吗?

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:23:19 28 4
gpt4 key购买 nike

来自 emplace_back() 的文档摘录:

  • Iterator validity

All iterators related to this container are invalidated, but pointers and references remain valid, referring to the same elements they were referring to before the call.

  • Data races

The container is modified.

No contained elements are accessed by the call: concurrently accessing or modifying them is safe (although see iterator validity above).

以及来自 operator[]() 的文档摘录:

  • Data races

The container is accessed (neither the const nor the non-const versions modify the container).

Element n is potentially accessed or modified. Concurrently accessing or modifying other elements is safe.

因此,鉴于 deque 的某个实例至少有一个元素,通过 operator[]() 访问它并调用 emplace_back() 在容器上并发确实是线程安全的?

我倾向于说是,但无法确定 emplace_back() 文档中的“访问”是否包括使用 operator[]() 如:

int access( std::deque< int > & q )
{
return q[ 0 ];
}

void emplace( std::deque< int > & q , int i )
{
q.emplace_back( i );
}

同时调用两个函数,或者“访问”仅适用于已采用某些引用或指针的元素:

std::deque< int > q { 1 };

auto * ptr = & q[ 0 ]

std::thread t1 ( [ ptr ]{ * ref = 0; } );
std::thread t2 ( [ & q ]{ q.emplace_back( 2 ); } );

编辑:为了进一步引用,以下是 C++ 14 标准(实际上是 November 2014 Working Draft, N4296)关于在 deque 中插入关于引用和迭代器有效性的说明:

  • 23.3.3.4 deque modifiers

(...)

  1. Effects: An insertion in the middle of the deque invalidates all the iterators and references to elements of the deque. An insertion at either end of the deque invalidates all the iterators to the deque, but has no effect on the validity of references to elements of the deque.

(...)

最佳答案

在标准类的对象上同时调用任何两个方法都是不安全的,除非两者都是 const,或者除非另有说明(例如 std::mutex::锁定())。对此进行了更详细的探讨 here

因此,同时使用 emplace_backoperator[]安全的。但是,由于引用/指针有效性,您可以安全地使用先前获得的对 deque 元素的引用,同时调用 emplace_back/push_back您引用的规则,例如:

int main()
{
std::deque<int> d;
d.push_back(5);
auto &first = d[0];
auto task = std::async(std::launch::async, [&] { first=3; });
d.push_back(7);
task.wait();
for ( auto i : d )
std::cout << i << '\n';
}

这将安全地输出 3 和 7。请注意,引用 first 是在启动异步任务之前创建的。

关于c++ - 从 std::deque 线程安全地同时调用 emplace_back() 和 operator[]() 吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41001062/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com