如何正确地将变量传递给线程中的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);
}
显示的逻辑有几个问题。
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
向量。有两种基本的方法来正确地做到这一点:
使用
reserve()
以确保没有重新分配随后发生。首先用所有的值填充矢量,然后产生所有的线程,传递给每个线程在现在完成的矢量中引用它自己的参数。
您有几种方法来解决这些问题:
第一填充载体,或保留其内容,然后传递给每个线程不是
fileHandler
的unique_ptr,但到unique_ptr
参考已经填充的fileHandlers
数组。可替代地,有可能避免任一保留,或者通过切换到
shared_ptr
小号填充向量提前,并捕获由值每个线程的shared_ptr
参数。
您能否提供代码示例?因为我来自Java环境,所以我不太确定我是否正确地理解了一切。 –
注意'std :: move(fileHandler)'。您尝试在之后立即访问它。尝试使用'fileHandlers.back()'来获取最新的文件处理程序。 –
在你移回处理程序后,你的'fileHandler'仍然处于未指定状态,这很可能意味着它不再指向任何东西。接下来,您将lambda存储在持久超过函数返回的容器中的线程中。所以,当线程加入时,lambda内部的'fileHandler'是一个悬挂的引用,它指向一个已经移动的不存在的值 - 即使在它存在的时候也是如此。 – bipll