在构造函数中构造 lambda

问题描述 投票:0回答:1

在使用基于回调的事件系统时,在构造函数中构造 lambda 时,我遇到了一些严重的错误。 这是简单的场景:

class Object {
public:
    int variable = 10;
    std::function<void()> callback;

    Object() {
        callback = [this]() {
            variable += 10;
        };
    }
};

class ObjectReceiver {
public:
    Object object;

    explicit ObjectReceiver(Object &&hi) : object(std::move(hi)) {}
};

int main() {
    ObjectReceiver receiver{Object()};
    receiver.object.callback();
    std::cout << receiver.object.variable << std::endl;
    return 0;
}

这里将打印“10”,因为对象被移动,并且 lambda 所持有的指针失效。

这意味着在

Object
之外的代码中,我应该始终关心它是否在其构造函数中构造 lambda。

遇到此类问题如何处理?我应该为自己制定一个通用约定,不要从构造函数构造 lambda 表达式吗?

c++ lambda callback object-construction
1个回答
0
投票

问题在于,调用

receiver.object.callback();
使用参数
this
进行操作,该参数指向由
Object
中的构造函数
Object()
创建的
ObjectReceiver receiver{Object()};
的临时实例。即使您按值传递所有内容并完全避免移动语义,您仍然会遇到相同的问题。根本问题是,当应用移动语义将
this
的临时实例复制到存储在
Object
中的实例时,
receiver.object
是按值传递的,并且不会更新。

要使其工作,您需要使 lambda 相对于它所应用的

Object
实例,如下所示:

class Object {
public:
    int variable = 10;
    std::function<void(Object& o)> raw_callback;
    void callback() { raw_callback (*this); }

    Object() {
        raw_callback = [](Object& o) {
            o.variable += 10;
        };
    }
};
© www.soinside.com 2019 - 2024. All rights reserved.