在两个 lambda 之间共享变量
Share variable between two lambdas
我希望能够在两个 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]
,无论我是否使用 mutable
,它都会抛出一个 EXC_BAD_ACCESS
。
我对其他实现内联函数的语言的经验是,这应该是可能的。例如 javascript:
var a = 10;
var b = function() {
a += 2;
}
var c = function() {
a += 3;
}
b();
c();
alert(a);
会提醒 15
。
我需要做什么才能让两个 lambda 函数引用相同的 identifierCollection 实现?因此它的行为方式与 javascript 示例相同。
如果您将地图包裹在 std::shared_ptr
中,那么生命周期将自动管理。然后,您的 lambda 可以按值捕获,它将获得对地图的引用,该地图的生命周期在 lambda 函数 returns.
之前一直有效
为此,请将您的地图定义更改为:
auto identifierCollection = std::make_shared<std::map<int,bool>>();
然后对映射成员函数的任何调用都需要从使用 .
更改为 ->
(因为它现在是一个指针)。
与某些脚本语言不同,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);
}
我希望能够在两个 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]
,无论我是否使用 mutable
,它都会抛出一个 EXC_BAD_ACCESS
。
我对其他实现内联函数的语言的经验是,这应该是可能的。例如 javascript:
var a = 10;
var b = function() {
a += 2;
}
var c = function() {
a += 3;
}
b();
c();
alert(a);
会提醒 15
。
我需要做什么才能让两个 lambda 函数引用相同的 identifierCollection 实现?因此它的行为方式与 javascript 示例相同。
如果您将地图包裹在 std::shared_ptr
中,那么生命周期将自动管理。然后,您的 lambda 可以按值捕获,它将获得对地图的引用,该地图的生命周期在 lambda 函数 returns.
为此,请将您的地图定义更改为:
auto identifierCollection = std::make_shared<std::map<int,bool>>();
然后对映射成员函数的任何调用都需要从使用 .
更改为 ->
(因为它现在是一个指针)。
与某些脚本语言不同,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);
}