如果容器不是调用函数中的引用,则使用 std::thread 传递对迭代器的引用将失败

Passing reference to iterator with std::thread fails if container is not a reference in calling function

本文关键字:引用 thread std 失败 迭代器 调用 函数 如果      更新时间:2023-10-16

这是我的问题:

我有一个带有容器成员的类,比如说std::vector.我有一个功能,比如说parallelStuff它引用这个容器的迭代器并用它做一些事情。我想使用std::thread并行执行所述函数

我已经实现了这个,它工作正常。现在我想写一个非常相似的设置,但有一个很小的区别:在工作版本中,在parallelStuff上调用线程的函数中,我从对容器的引用中获取迭代器。

但是,如果我从非引用容器获取迭代器,则编译将失败。

这是一个复制问题的最小示例:

#include <thread>
#include <vector>
class Foo {
public:
Foo() {}
auto const & member() { return member_; }
void parallelStuff(std::vector<int>::const_iterator & it,
std::vector<int>::const_iterator const & end) {
// do stuff while it != end
}
private:
std::vector<int> member_;
};

int main(int argc, char * argv[]) {
auto foo = Foo();
auto& member = foo.member();
// auto member = foo.member();  <-- copy instead of reference, this fails!
auto it = member.begin();
auto end = member.end();
auto t = std::thread(&Foo::parallelStuff, &foo,
std::ref(it), std::ref(end));
t.join();
return 0;
}

如前所述,如果我使用member的副本而不是引用,则会出现错误

/usr/include/c++/8/thread:120:17: error: static assertion failed: std::thread arguments must be invocable after conversion to rvalues

谷歌搜索错误消息只把我带到了一个网站,解释说我需要将引用参数包装在我已经这样做的std::ref()中。

有没有人了解这里出了什么问题,可以解释一下(以及如何解决这个问题)?

非常感谢!

PS:我使用gcc version 8.3.0 (Ubuntu 8.3.0-6ubuntu1~18.04)-std=c++17

函数parallelStuff希望获得常量迭代器,您必须提供它们。

你可以得到常量迭代器

  1. 通过在对象上调用cbegin/cend

  1. 通过调用begin/end在 const 对象

在下面的行中

auto member = foo.member();

自动类型推导的工作原理是从初始值设定项中丢弃引用性和恒定性。所以member只是被宣布为vector<int>.因此,begin/end返回vector<int>::iteratorparallelStuff参数不匹配的内容。

要在非常量对象上获取常量迭代器,只需调用cbegin/cend

auto it = member.cbegin();
auto end = member.cend();

现场演示


这行得通

auto& member

因为member被推导为const vector<int>&,所以在 const 对象上调用的begin/end返回 const 迭代器 -vector<int>::const_iteratorparallelStuff声明匹配。