在两个 lambda 表达式之间共享变量 [英] Share variable between two lambdas

查看:42
本文介绍了在两个 lambda 表达式之间共享变量的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我希望能够在两个 lambda 函数之间的包含范围内共享一个变量.我有以下几点:

I want to be able to share a variable in the containing scope between two lambda functions. I have the following:

void holdAdd(const Rect& rectangle, Hold anonymousHeld, Hold anonymousFinish) {
    std::map<int,bool> identifierCollection;

    HoldFinish holdFinish = [=](const int& identifier) mutable {
        if (identifierCollection.count(identifier) == 0) return;

        identifierCollection.erase(identifier);
        anonymousFinish();
    };

    holdCollisionCollection.push_back([=](const int& identifier, const Vec2& point) mutable {
        if (rectangle.containsPoint(point)) {
            identifierCollection[identifier] = true;
            anonymousHeld();
        } else {
            holdFinish(identifier);
        }
    });
    holdFinishCollection.push_back(holdFinish);
}

我可以在调试器中看到 holdFinish 指向的 identifierCollection 实现与第二个 lambda 函数不同.

I can see in the debugger that holdFinish is pointing to a different implementation of identifierCollection than in the 2nd lambda function.

如果我使用 [=, &identifierCollection] 它会抛出一个 EXC_BAD_ACCESS 无论我是否使用 mutable.

If I use [=, &identifierCollection] it throws a EXC_BAD_ACCESS whether I use mutable or not.

我对其他实现内联函数的语言的经验是,这应该是可能的.例如在 javascript 中:

My experience with other languages that implement inline functions is that this should be possible. For instance in javascript:

var a = 10;
var b = function() {
    a += 2;
}
var c = function() {
    a += 3;
}
b();
c();
alert(a);

会提醒 15.

我该怎么做才能让两个 lambda 函数引用相同的 identifierCollection 实现?这样它的行为方式与 javascript 示例相同.

What do I have to do to get both lambda functions to reference the same identifierCollection implementation? So that it behaves in the same way as the javascript example.

推荐答案

与某些脚本语言不同,identifierCollection 的生命周期不会仅仅因为您将其捕获到闭包中而延长.因此,一旦您将 [=] 更改为 [&] 以通过引用捕获,它就是对您正在捕获的局部变量的悬空引用.

Unlike in some scripting languages, identifierCollection's lifetime won't be extended simply because you captured it into a closure. So as soon as you change that [=] for a [&] to capture by reference, it's a dangling reference to a local variable that you're capturing.

您必须自己管理 identifierCollection 的生命周期;坦率地说,这听起来像是共享指针的绝佳机会,通过值捕获到每个 lambda 中.只要您需要,它所包装的动态分配的地图就会一直存在.

You'll have to manage the lifetime of identifierCollection yourself; frankly, this sounds like the perfect opportunity for a shared pointer, captured by value into each lambda. The dynamically-allocated map it wraps will literally exist for as long as you need it to.

void holdAdd(const Rect& rectangle, Hold anonymousHeld, Hold anonymousFinish)
{
    auto identifierCollection = std::make_shared<std::map<int,bool>>();

    HoldFinish holdFinish = [=](const int& identifier) mutable {
        if (identifierCollection->count(identifier) == 0) return;

        identifierCollection->erase(identifier);
        anonymousFinish();
    };

    holdCollisionCollection.push_back([=](const int& identifier, const Vec2& point) mutable {
        if (rectangle.containsPoint(point)) {
            (*identifierCollection)[identifier] = true;
            anonymousHeld();
        } else {
            holdFinish(identifier);
        }
    });
    holdFinishCollection.push_back(holdFinish);
}

这篇关于在两个 lambda 表达式之间共享变量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆