首页 > 解决方案 > 如果容器不是调用函数中的引用,则使用 std::thread 传递对迭代器的引用失败

问题描述

这是我的问题:

我有一个带有容器成员的类,比如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)with-std=c++17

标签: c++multithreadingreferencestliterator

解决方案


函数parallelStuff期望获得const 迭代器,您必须提供它们。

您可以获得const 迭代器

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

或者

  1. 通过调用begin/endconst 对象上

在下面的行中

auto member = foo.member();

自动类型推导有效,它丢弃了初始化程序的引用性和常量性。所以member只是声明为vector<int>. 因此begin/end返回与 .vector<int>::iterator的参数不匹配的内容parallelStuff

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

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

现场演示


这有效

auto& member

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


推荐阅读