【问题标题】:Thread Constructor Initialization C++线程构造函数初始化 C++
【发布时间】:2021-06-30 08:26:28
【问题描述】:

我一直在尝试编写一个简单的程序来试验线程向量。我目前正在尝试创建一个线程,但我发现我遇到了一个错误,即我的构造函数没有正确初始化,错误是没有匹配参数列表的 std::thread 构造函数。这是我所做的:

#include <functional>
#include <iostream>
#include <numeric>
#include <thread>
#include <vector>

int sum = 0; 
void thread_sum (auto it, auto it2, auto init) {
  sum = std::accumulate(it, it2, init);
}

int main() {
  // * Non Multi-Threaded
  // We're going to sum up a bunch of numbers.
  std::vector<int> toBeSummed;
  for (int i = 0; i < 30000; ++i) {
    toBeSummed.push_back(1);
  }
  // Initialize a sum variable
  long sum = std::accumulate(toBeSummed.begin(), toBeSummed.end(), 0);

  std::cout << "The sum was " << sum << std::endl; 
  // * Multi Threaded
  // Create threads
  std::vector<std::thread> threads;
  std::thread t1(&thread_sum, toBeSummed.begin(), toBeSummed.end(), 0);
  std::thread t2(&thread_sum, toBeSummed.begin(), toBeSummed.end(), 0);
  threads.push_back(std::move(t1));
  threads.push_back(std::move(t2));
  return 0; 
}

搞砸的行如下:

  auto t1 =
      std::thread {std::accumulate, std::ref(toBeSummed.begin()), 

这是构造函数的问题。我尝试了 std::ref、std::function 和其他包装器的不同组合,并尝试将我自己的函数 lambda 对象作为累积的包装器。

以下是一些附加信息:

错误信息是:atomics.cpp:28:7: error: no matching constructor for initialization of 'std::thread'

此外,当悬停在构造函数上时,它告诉我第一个参数是

我尝试过的其他尝试:

  • 使用引用而不是常规值参数
  • 使用std::bind
  • 使用std::function
  • 在变量中声明函数并将其作为我的第一个参数传递给构造函数
  • 使用不同的标志编译,例如std=c++2a

编辑

  1. 我会留下最初的问题,让其他人从我的错误中吸取教训。正如我接受的答案将显示的那样,这是由于我过度使用 auto。我读过一本 C++ 书,基本上说“总是使用 auto,它更易读!就像 Python 和动态类型,但具有 C++ 的性能”,但显然这不能总是做到。 using 关键字提供了可读性,同时仍然安全。感谢您的回答!

【问题讨论】:

  • std::thread t1(, toBeSummed.begin(), toBeSummed.end(), 0); 看起来坏了。它缺少第一个参数。
  • 如果您想检索累加函数的结果,您可能更喜欢asyncpackaged_task,它们可以为您提供未来的结果。
  • 你的线程代码中有一些未定义的行为,你不要在启动它们之后加入线程,在退出之前加入它们,或者如果你有 c++20 的 jthread 可用,请改用它。跨度>

标签: c++ concurrency


【解决方案1】:

您遇到的问题是因为std::accumulate 是一个重载的函数模板,因此编译器不知道将其作为参数传递给线程构造函数时将其视为什么特定函数类型。由于auto 参数,您的thread_sum 函数也会出现类似问题。

您可以选择std::accumulate 的特定重载/实例化,如下所示:

  std::thread t2(
      (int(*)(decltype(toBeSummed.begin()), decltype(toBeSummed.end()), int))std::accumulate,
       toBeSummed.begin(), toBeSummed.end(), 0);

【讨论】:

    【解决方案2】:

    问题是您过度使用auto。您可以通过更改这一行来修复它:

    void thread_sum (auto it, auto it2, auto init) {
    

    到这里:

    using Iter = std::vector<int>::const_iterator;
    void thread_sum (Iter it, Iter it2, int init) {
    

    【讨论】:

      猜你喜欢
      • 2018-06-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-25
      相关资源
      最近更新 更多