无法在异步Lambda中访问std :: vector *

问题描述

我需要生成一堆随机数,并使用(只是读取)它们来自不同的线程。这是我生成数字的方法

const std::vector<double>* Test::getRandomDoubles(int count)
{
    std::vector<double>* numbers = new std::vector<double>();
    numbers->reserve(count);

    for (int i = 0; i < itemsCount; i++)
    {
        srand((int)std::chrono::high_resolution_clock::Now().time_since_epoch().count());
        numbers->emplace_back(rand() / 1000);
    }
    return numbers;
}

但是我有时会丢失数字:

std::future<void> SomeMethod(const std::vector<double>& numbers)
{
    return std::async( // breakpoint: numbers are available when creating the future.
        std::launch::async,[&]()
        {  // breakpoint: numbers gone. <-
            // Use numbers

如果有帮助,我可以这样调用SomeMethod:

// Just want to run some test for SomeMethod.
std::vector<void> futures;
for(int i = 0; i < 10; i++)
{
   std::vector<double> numbers = *getRandomDoubles(count);
   futures.emplace_back(SomeMethod(numbers));
}
for(int i = 0; i < 10; i++)
{
    futures[i].get();
}

目前,我没有在代码中的任何地方调用delete。

我应该怎么做才能在异步lambda中包含数字?

解决方法

您有责任确保lambda不会超过它通过引用捕获的变量。

如果从函数返回一个lambda,则在调用它时,它已捕获的局部变量早就死了。如果异步运行它并返回future,则会发生同样的事情。

克服此问题的一种方法是通过复制或by move进行捕获。

偶然地,getRandomDoubles()应该调用new并返回一个指针。 C ++不是Java。写

std::vector<double> Test::getRandomDoubles(int count) {
    std::vector<double> numbers;
    ...
    return numbers;
}
,

您捕获的向量是一个副本,而不是您动态分配的副本:

std::vector<double> numbers = *getRandomDoubles(count);

这一行完成后,原始向量将永远作为泄漏的内存消失。将numbers用作参考以避免复制。作为警告,如果您不想将其复制或移动到异步代码中,请确保同步访问该共享可变状态。