【问题标题】:Compiler Error variable "Not captured" inside lambda function for threadpool线程池的 lambda 函数内的编译器错误变量“未捕获”
【发布时间】:2015-12-05 05:01:00
【问题描述】:

我正在学习 C++ 中的多线程,并试图建立一个线程池,但我收到一个编译器错误,提示“错误:'mapperNodes' 未被捕获”和“错误:'command' 未被捕获”。我已经阅读了一些关于使用“this”来捕获 lambda 中的变量的信息,但到目前为止还没有任何效果。

如何在下面的代码中使用线程池lambda函数中的command和mapperNoders变量?

void MapReduceServer::spawnMappers() throw() {
  vector<string> mapperNodes(nodes);
  random_shuffle(mapperNodes.begin(), mapperNodes.end());
  string command = buildCommand(mapperNodes[0], executablePath, mapperExecutable, mapOutputPath);

  ThreadPool pool(numMappers);//numMappers = 8

  for (size_t id = 0; id < numMappers; id++) {
    pool.schedule([id] {
      cout << oslock << "Thread (ID: " << id << ") has started." << endl << osunlock;

      spawnWorker(mapperNodes[0], command); /*compiler error here*/

      cout << oslock << "Thread (ID: " << id << ") has finished." << endl << osunlock;
  });
}

【问题讨论】:

  • @MM,我认为你错了。 TC++PL 第 4 版第 11.4.4 节。明确表示可以省略空参数列表。例如,this article in cppreference.com 也是如此。
  • @Paulo1205 很酷,很高兴知道

标签: c++ multithreading lambda scope


【解决方案1】:

当您编写 pool.schedule([id]{ /*...*/ }); 时,您告诉编译器您的 lambda 只需要 一份 id 变量值的副本,而不需要其他任何内容。

要使 MapReduceServer::spawnMappers() 的所有变量(副本)可用于 lambda,您可以将 [id] 更改为 [=]

【讨论】:

  • 话虽如此,您可能不想要所有可用变量的副本
  • @JoelCornett,同意,变量 pool 可以省略。也许他应该改用[id, command, mapperNodes]
  • [&amp;][=] 最简单,通常也是最好的;命名特定成员并没有真正获得任何好处,实际上可能会损害性能
  • @MM,我只是认为[&amp;](或[&amp;somevar])在这种情况下不会好,因为据我所知,他正在创建新线程,作为提供参考将临时对象添加到可能比其创建者寿命更长的线程可能不是一个好主意。
  • @M.M:怎么会这样?工作中是否存在利用完整捕获的底层优化?
猜你喜欢
  • 1970-01-01
  • 2013-05-28
  • 2016-10-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-11-07
  • 2013-09-23
相关资源
最近更新 更多