2016-08-04 26 views
3

在下面的功能,我可以依靠捕獲變量「秩序」是最新的,即只是當lambda捕獲初始化?

  1. 將如預期的功能始終正常工作?
  2. 按價值或參考值進行捕獲是否存在差異?
  3. 函數是否可重入?
struct Entry 
{ 
    std::string name; 
    double earnings; 
}; 

enum Column { Name, Earnings }; 
enum SortOrder { Ascending, Descending }; 

void sortByColumn(std::vector<Entry>& entries, Column column, SortOrder order) 
{ 
    std::function<bool(const Entry&, const Entry&)> comparators[] = 
    { 
     [&](const Entry& a, const Entry& b) { return order==Ascending ? 
      a.name < b.name : a.name > b.name; }, 
     [=](const Entry& a, const Entry& b) { return order==Ascending ? 
      a.earnings < b.earnings : a.earnings > b.earnings; } 
    }; 
    std::sort(entries.begin(), entries.end(), comparators[column]); 
} 

你可以找到一個完整的例子在這裏:http://coliru.stacked-crooked.com/a/240b74d1706a1b6f

+0

[在C++ 11中,lambda表達式的綁定變量何時應該按值捕獲?]的可能重複(http://stackoverflow.com/questions/7881149/in-c11-when-are -a-lambda-expressions-bound-variables-expected-to-be-captured) –

+1

@JamesElderfield我會爭辯說,這不是對鏈接問題的一個騙局,因爲它詢問MSVC行爲。答案是相關的,但問題本身不是一個騙局。 –

回答

2

,你必須認識到的是,一個lambda是一個封閉類型的對象:

Lambda表達式是prvalue表達式唯一的未命名的非工會非聚合類類型的無名臨時對象,稱爲閉包類型,它在最小的塊作用域,類作用域或命名空間作用域中聲明(用於參數相關查找),其中包含羊肉DA表達[source]

你可以認爲拉姆達的捕獲列表構造函數的參數的。在這種情況下,您將值分別通過order分別轉換爲,ndcomparators由於ordercomparators的生存期內不會改變,所以在您的示例中,通過引用或值傳遞將具有相同的結果。

但是,如果這個功能用order集叫Ascending並添加這一對的sortByColumn底部:

order = Descending; 
std::sort(entries.begin(), entries.end(), comparators[0]); 

你會通過name分類entries降序秩序。意思是order的變化影響了lambda。

如果您想不過做到了這一點,並sortByColumn再次通過orderAscending

order = Descending; 
std::sort(entries.begin(), entries.end(), comparators[1]); 

你會通過earnings上升秩序已經整理entries。這意味着對order的更改不會影響lambda。


在決定是否通過參考捕捉到相同的考慮應該適用,你在決定是否要使用參考或複製的對象成員使用:

  1. 你必須使用一個參考如果對象無法複製構建,並且您可能需要選擇以使用參考(如果複製構造昂貴)
  2. 如果lambda的生命週期將超過其捕獲的生命週期,則您必須複製副本可能選擇使用進行復印,如果您提供的拉姆達在外部使用你的代碼
2
  1. 的代碼按預期工作。
  2. 當然,這是有區別的。儘管在這個例子中它並沒有改變最終結果,但我更願意用值來捕獲。原因在於它只是您捕獲的基本類型,並且在lambda中沒有寫入操作。此外,這是良好的作風,始終明確地捕捉:
std::function<bool(const Entry&, const Entry&)> comparators[] = 
    { 
     [order](const Entry& a, const Entry& b) { return order==Ascending ? a.name < b.name : a.name > b.name; }, 
     [order](const Entry& a, const Entry& b) { return order==Ascending ? a.earnings < b.earnings : a.earnings > b.earnings; } 
    }; 
  • sortByColumn是折返。除了改變entries之外,它沒有狀態,也沒有副作用。
  • 如果你關心性能,這是檢查lambda表達式外的排序order並直接傳遞lambda來std::sort,而不是把它變成一個第一個std::function好主意。你需要四個不同的lambda強硬。