在两个 lambda 之间共享变量



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

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指向与第二个 lambda 函数不同的identifierCollection实现。

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

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

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

会提醒15.

我该怎么做才能让两个 lambda 函数引用相同的标识符集合实现?因此它的行为方式与 JavaScript 示例相同。

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

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

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);
}

如果将地图包装在std::shared_ptr中,则将自动管理生存期。然后,您的 lambda 可以按值捕获,它将获得对映射的引用,该映射的生存期在 lambda 函数返回之前一直有效。

为此,请将地图定义更改为:

auto identifierCollection = std::make_shared<std::map<int,bool>>();

然后,对映射成员函数的任何调用都需要从使用 . 更改为->(因为它现在是一个指针)。

最新更新