如何正确地将变量传递给线程中的lambda函数

问题描述:

我在这段代码中有泄漏。我知道我正在向vector传递对象,并且错误地将lambda函数传递给lambda函数,但我不确定如何解决这个问题。您能否给我任何代码审查和更正?如何正确地将变量传递给线程中的lambda函数

std::vector<std::thread> threads; 
std::vector<std::unique_ptr<FileHandler>> fileHandlers; 

for (std::string argument : filesToParse) 
{ 
    std::unique_ptr<FileHandler> fileHandler(new FileHandler(argument)); 
    fileHandlers.push_back(std::move(fileHandler)); 

    threads.push_back(std::thread([&fileHandler]() 
    { 
     fileHandler->processFile(); 
    })); 
} 

for(auto i = 0; i < threads.size(); ++i) 
{ 
    threads.at(i).join(); 
    fileHandlers.at(i)->mergeMaps(finalMap); 
} 
+2

注意'std :: move(fileHandler)'。您尝试在之后立即访问它。尝试使用'fileHandlers.back()'来获取最新的文件处理程序。 –

+0

在你移回处理程序后,你的'fileHandler'仍然处于未指定状态,这很可能意味着它不再指向任何东西。接下来,您将lambda存储在持久超过函数返回的容器中的线程中。所以,当线程加入时,lambda内部的'fileHandler'是一个悬挂的引用,它指向一个已经移动的不存在的值 - 即使在它存在的时候也是如此。 – bipll

显示的逻辑有几个问题。

fileHandlers.push_back(std::move(fileHandler)); 

fileHandler的的unique_ptr已经搬走了这里的内容。紧接着这一点:

threads.push_back(std::thread([&fileHandler]() { 

这传递,每一个新的线程,为unique_ptr其内容参考刚从搬走。这unique_ptr去了它的制造商。它不复存在。加入了无形的合唱团。这是一个ex-unique_ptr

fileHandlers.push_back(std::move(fileHandler)); 

返回声明。在这里,你会得到一个价格的两个逻辑错误。

fileHandlers是一个载体。向矢量添加值可能会重新分配矢量。重新分配会使所有现有迭代器,指针或对矢量现有内容的引用无效。通过引用此向量中的某个元素,然后在下一次迭代循环中向此向量添加某些内容时,如果向量重新分配,则会在您的面部爆炸。

这里的显而易见的意图是向所有线程填充所有参数列表的fileHandlers向量。有两种基本的方法来正确地做到这一点:

  1. 使用reserve()以确保没有重新分配随后发生。

  2. 首先用所有的值填充矢量,然后产生所有的线程,传递给每个线程在现在完成的矢量中引用它自己的参数。

您有几种方法来解决这些问题:

  1. 第一填充载体,或保留其内容,然后传递给每个线程不是fileHandler的unique_ptr,但到unique_ptr参考已经填充的fileHandlers数组。

  2. 可替代地,有可能避免任一保留,或者通过切换到shared_ptr小号填充向量提前,并捕获由值每个线程的shared_ptr参数。

+0

您能否提供代码示例?因为我来自Java环境,所以我不太确定我是否正确地理解了一切。 –