1

我很好奇为什么这会在大约 1 次运行中崩溃 4 次。

我有一个简单的类,它返回一个带有线程 ID 的字符串。此类在 lambda 中从另一个类中异步调用并返回结果。代码尽可能简单 - 我仍在学习:

class String_Returner
{
public:
    string run() const
    {
        return "I returned from thread "+to_string(this_thread::get_id());
    }
};

class Class_Holder
{
public:
    Class_Holder() : number_of_runs(10)
    {
        srs.resize(number_of_runs);
    }

    void concurrent_srs()
    {
        for (int i = 0; i < number_of_runs; i++)
        {
            results.push_back(async([&]{return srs[i].run();}));
        }

        for (int i = 0; i < results.size(); i++)
        {
            cout << i << ") " << results[i].get() << endl;
        }

        results.clear();
    }
private:
    vector<future<string>> results;
    vector<String_Returner> srs;
    const int number_of_runs;
};

void class_b_test()
{
    Class_Holder ch;
    ch.concurrent_srs();
}

我意识到将异步与引用一起使用是危险的,但我认为如果什么都不写是安全的。我认为我的错误可能来自 lambda 本身。这主要是一个测试 async 和 lambdas 功能的程序。

所以我的主要问题是:1)为什么会崩溃?2)有什么更好的方法可以做到这一点?

4

2 回答 2

4

为什么会崩溃?

results.push_back(async([&]{return srs[i].run();}));

该行中的引用没有任何问题srs;正如你所说,它没有被修改。但是引用i是完全没有意义的;ilambda 执行时可能不再存在,其值将不可预测。

但我不明白为什么你觉得需要不止一个StringReturner。该类没有状态,并且该run方法也可能是静态的,因为它产生的所有差异。

有什么更好的方法可以做到这一点?

做什么,究竟是什么?

于 2013-07-04T06:58:45.413 回答
1

如果你无论如何都要使用一个 lambda,为什么不直接使用一个直接做你想做的事:

#include <string>
#include <iostream>
#include <thread>
#include <future>
#include <sstream>
#include <vector>

int main() { 
    std::vector<std::future<std::string>> rets;

    auto f = []() {
        std::ostringstream b;
        b << "returned from: " << std::this_thread::get_id();
        return b.str();
    };

    for (int i=0; i<10; i++)
        rets.emplace_back(std::async(f));

    for (auto & t : rets) {
        t.wait();
        std::cout << t.get() << "\n";
    }
}

请注意,返回的thread::id类型get_id保证具有operator<<,但至少据我所知,不能保证它是std::to_string已重载的类型。

于 2013-07-04T06:58:24.260 回答