std :: async lambda函数内部的局部变量的生命周期

时间:2019-02-12 15:07:59

标签: c++ lambda lifetime local-variables stdasync

在以下代码段中:

std::future<bool> result = std::async(std::launch::async, []()
{
    std::vector<char*> someLocalVariable{GottenFromSomewhere()};
    return SomeReallyLongLastingProcessingPipeline(someLocalVariable);
});

我倾向于说someLocalVariable无疑会比SomeReallyLongLastingProcessingPipeline()调用有效,即使这全部发生在传递给std :: async的lambda中。这是真的?

我不得不提到std::future是在SomeReallyLongLastingProcessingPipeline()之前构造的对象内部,并在该函数退出后被破坏。

1 个答案:

答案 0 :(得分:2)

您发布的代码本身看起来还不错,但std::vector中的char*使我感到怀疑。您的评论“ ...但是,我担心的是someLocalVariable本身依赖于所有此代码段所在的方法结尾超出范围的内容,这可能使事情搞砸了,对吧?”强调我的怀疑:

是的,someLocalVariable的寿命比SomeReallyLongLastingProcessingPipeline长,但不一定是char*中指向std::vector的事物。您的问题可能是GottenFromSomewhere,在执行整个lambda时,someLocalVariable充满了指向不活跃内容的指针。因此它在someLocalVariable的构造函数中可能存在,或者可能已经“死”,而SomeReallyLongLastingProcessingPipeline的情况也是如此。

但是,这使您无法获得完整的代码。

改为使用std::vector<std::string>


评论更新:

#include <iostream>
#include <future>
#include <string>
#include <vector>
#include <memory>

bool SomeReallyLongLastingProcessingPipeline(std::vector<const char*> data) {
    return data.at(0)[0] == 'L';
}

//Prefer this one
bool SomeReallyLongLastingProcessingPipeline(std::vector<std::shared_ptr<const std::string>> data) {
    return data.at(0)->find('L');
}

std::future<bool> foo() {

    auto big_string_you_wont_change_until_lambda_finished = std::make_shared<std::string>("Long long text "
                                                                  "(>should be at least several dozen kB");
    //You could also use std::shared_ptr foo{new std::string("ff")}; but make_shared is safer (exception safety)

    //beware of lambda capture, DO NOT just use [&] or [&big_string_you_wont_change_until_lambda_finished]
    //use [=] or [big_string_you_wont_change_until_lambda_finished] is ok
    std::future<bool> result = std::async(std::launch::async, [big_string_you_wont_change_until_lambda_finished]()
    {
        std::vector<const char*> someLocalVariable{big_string_you_wont_change_until_lambda_finished->c_str()};
        std::vector<std::shared_ptr<const std::string>> someBetterLocalVariable
        {big_string_you_wont_change_until_lambda_finished};

        return SomeReallyLongLastingProcessingPipeline(someLocalVariable) || //I recommend the last one
        SomeReallyLongLastingProcessingPipeline(someBetterLocalVariable);
    });
    return result;
}

int main() {

    auto future = foo();

    std::cout << future.get() << "\n";

    return 0;
}