【问题标题】:capture std::function by value按值捕获 std::function
【发布时间】:2012-04-01 19:53:14
【问题描述】:

我使用以下代码:

struct WorkData
{
    std::string name;
    std::function<void(std::string)> Callback;

    WorkData(){};
    WorkData(const WorkData& other)
    {
        name = other.name;
        Callback = std::ref(other.Callback);
    }
};

WorkData data; // this is the data to pass to queue_task() function bellow
data.Callback = std::bind(&ResultProcessor::Handler, resProc, std::placeholders::_1);

template <typename Functor>
void queue_task(Functor& fn, WorkData& workData )
{
    group.run([&fn, workData](){
          workData.Callback("resultComming"); // runtime ERROR- access violation
    });
}

queue_task 函数队列工作在另一个线程上异步完成(通过从上面调用 group.run(lambda) )。我遇到的问题是尝试调用 workData.Callback() 时遇到访问冲突。

我在 group.run() 中复制 workData 的原因是因为我想按值捕获 workData 以便当 group.run() lambda 执行时它具有调用 queue_task() 时的状态副本.我希望 workData.Callback() 将在在线传递的对象实例上执行:

data.Callback = std::bind(&ResultProcessor::Handler, resProc, std::placeholders::_1);

编辑:调用崩溃线时,上面的 resProc 是活动的(未销毁)

【问题讨论】:

    标签: c++ lambda crash


    【解决方案1】:

    在复制构造函数中使用std::ref 意味着您保留对旧WorkDataCallback 成员的引用,而不是副本。您希望Callback = other.Callback 制作副本以避免访问冲突(可能是在释放旧回调后访问它)。为了在std::function 中保留对resProc 的引用,您需要在对std::bind 的调用中使用std::ref(resProc)

    【讨论】:

    • 我刚刚在我的问题中添加了 EDIT。我使用 std::ref 因为否则我最终会在 ResultProcessor 的不同实例上调用 workData.Callback("resultComming")
    • 在这种情况下,您需要在ResultProcessor 上使用std::ref,而不是函数对象本身。即,在您的最后一个代码块中,您应该有 std::ref(resProc),然后在您的复制构造函数中使用 std::function 的真实副本。
    • ResultProcessor 实例与 std::function 一起传输 在 queue_task() 接口中作为 WorkData 的一部分回调
    • 我在您的代码中没有看到:您传入的是 WorkData 对象,而不是 queue_task 中的 ResultProcessor
    • 有一行代码WorkData data,这里我初始化data.Callback。我调用 queue_task 的数据
    猜你喜欢
    • 2013-12-15
    • 1970-01-01
    • 1970-01-01
    • 2015-11-22
    • 1970-01-01
    • 2015-03-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多