2015-06-13 241 views
0

我希望能夠在兩個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指向不同的實現的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函數引用相同的identifierCollection實現?因此,它的行爲與javascript示例相同。

+1

所以問題是,當你按值捕獲你已經捕獲的價值,當你通過引用捕獲你已經捕獲了一個懸浮的引用本地變量....你必須決定你想要的對象的生命週期。 –

+1

有沒有'[&]'工作?嘗試使地圖'靜態' – twentylemon

+2

將地圖包裹在'shared_ptr'中。 –

回答

4

與某些腳本語言不同,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); 
} 
+0

現在按預期工作。輝煌!謝謝:) – richardjsimkins

+0

雖然JavaScript不是一種腳本語言,儘管它的名字;)我會說它更多的是沒有垃圾回收的C++症狀。所以我認爲如果答案是「不同於有垃圾收集的語言」 – richardjsimkins

2

如果您將地圖封裝在std::shared_ptr中,則會自動管理生命期。然後你的lambda可以通過值捕獲,並且它將得到一個對其生命期一直保持有效的映射的引用,直到lambda函數返回。

要做到這一點,你的地圖定義修改爲:

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

然後到地圖的成員函數調用任何需要使用.更改爲->(因爲它現在是一個指針)。