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

时间:2017-01-05 20:35:59

标签: c++ multithreading 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);
}

1 个答案:

答案 0 :(得分:2)

显示的逻辑有几个问题。

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

fileHandler unique_ptr的内容已移至此处。紧接着:

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

这会向每个新主题传递对其内容刚刚离开unique_ptr的引用。这个unique_ptr已经去见了它的制造者。它不复存在。加入合唱团看不见。这是前任unique_ptr

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

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

fileHandlers是一个向量。向向量添加值可以重新分配向量。重新分配使所有现有的迭代器,指针或对向量的现有内容的引用无效。传递对此向量中某些内容的引用,然后在循环的下一次迭代中向该向量添加一些内容,如果向量重新分配,则会在您的脸上爆炸。

这里显而易见的意图是使用所有线程的所有参数列表填充fileHandlers向量。有两种基本方法可以正确完成:

  1. 使用reserve()确保不会再发生重新分配。

  2. 首先使用所有值填充向量,然后仅生成所有线程,向每个线程传递对现在完整向量中自己的参数的引用。

  3. 您有几种方法可以解决这些问题:

    1. 首先填充向量,或保留其内容,然后传递给不是fileHandler unique_ptr的每个线程,而是传递给unique_ptr数组中的fileHandlers已经填充。

    2. 或者,可以通过切换到shared_ptr并通过值 <捕获 来提前预留或填充向量/ strong>每个帖子的shared_ptr参数。