简体   繁体   English

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

[英]How to properly pass variable to lambda function in thread

I am having leaks in this piece of code. 我在这段代码中泄漏。 I know that I am passing objects to vector and to lambda function incorrectly, but I am not really sure how to solve that. 我知道我错误地将对象传递给vector和lambda函数,但是我不确定如何解决这个问题。 Could you please give me any code review and correction? 您能否给我任何代码审查和更正?

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);
}

There are several problems with the shown logic. 所示逻辑存在多个问题。

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

The contents of the fileHandler unique_ptr have been moved away here. fileHandler unique_ptr的内容已移至此处。 Immediately after this: 在此之后立即:

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

This passes, to each new thread, a reference to a unique_ptr whose contents have just been moved away from . 这会向每个新线程传递对unique_ptr的引用,其内容刚刚从移走了 This unique_ptr is gone to meet its maker. 这个unique_ptr已经不见了它的制造商。 It ceased to exist. 它不再存在。 Joined the choir invisible. 加入了看不见的合唱团。 It's an ex- unique_ptr . 这是一个ex- unique_ptr

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

Back to this statement. 回到这句话。 You get two logical errors for the price of one, here. 您会在这里得到两个逻辑错误,价格为一。

fileHandlers is a vector. fileHandlers是一个向量。 Adding a value to a vector may reallocate the vector. 向向量添加值可能会重新分配向量。 Reallocation invalidates all existing iterators, pointers, or references to the existing contents of the vector. 重新分配会使所有现有的迭代器,指针或对向量的现有内容的引用无效。 Passing a reference to something in this vector, then subsequently adding something to this vector on the next iteration of the loop will blow up in your face if the vector reallocates. 传递对该向量中某物的引用,然后在循环的下一次迭代中向该向量中添加某物,如果向量重新分配,则会在您的面前大怒。

The obvious intent here is to populate the fileHandlers vector with a list of all parameters to all threads. 这里的明显意图是用所有线程的所有参数的列表填充fileHandlers向量。 There are two basic ways to do it correctly: 正确执行此操作有两种基本方法:

  1. Use reserve() to make sure that no reallocation subsequently occurs. 使用reserve()确保随后不会发生重新分配。

  2. Populate the vector first, with all the values, and only then spawn off all the threads, passing to each thread a reference to its own parameter in the now-complete vector. 首先使用所有值填充向量,然后再生成所有线程,将现在完整的向量中对其自身参数的引用传递给每个线程。

You have several ways to fix these problems: 您有几种方法可以解决这些问题:

  1. Populate the vector first, or reserve its contents, then pass to each thread not the fileHandler unique_ptr, but a reference to the unique_ptr in the fileHandlers array that has already been populated. 首先填充向量,或保留其内容,然后将不是fileHandler unique_ptr传递给每个线程,而是传递对已经填充的fileHandlers数组中的unique_ptr的引用。

  2. Alternatively, it's possible to avoid either reserving, or populating the vector in advance by switching to shared_ptr s, and capturing by value each thread's shared_ptr parameter. 或者,可以通过切换到shared_ptr并按捕获每个线程的shared_ptr参数来避免保留或预先填充向量。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM