C++11 lambda表示式不能捕獲map/unordered_map值
先看一道面試題。
某公司中有N名員工,給定所有員工工資的清單,財務人員要按照持定的順序排列員工的工資,他按照工資的頻次降序排列,即給定清單中所有頻次較高的工資將在頻次較低的工資之前出現,如果相同數量的員工都有相同的工資,則將按照給定清單中該工資第一次出現的順序排列。
寫一演算法來幫助財務人員排列員工工資的順序。
輸入:
該函式/方法的輸入包括兩個引數——
num,一個整數,表示員工的人數。
salaries,一個正整數列表,表示N名員工的工資。
輸出:
返回一個正整數列表, 該列表按照員工工資的頻次排序。
約朿條件:
1 <= num <= 10^5
1 <= salaries[i]<=10^9
0 <= i < num
示例如下
輸入:
num=19
salaries=[10000,20000,40000,30000,30000,30000,40000,20000,50000,50000,50000,50000,60000,60000,60000,70000,80000,90000,100000]
輸出:
[50000,50000,50000,50000,30000,30000,30000,60000,60000,60000,20000,20000,40000,40000,10000,70000,80000,90000,100000]
程式碼:
#include <iostream> #include <unordered_map> #include <vector> #include <algorithm> using namespace std; vector<int> salaryfrequeny(int num, int *salaries) { unordered_map<int, int> cntm; unordered_map<int, int> posm; vector<int> res; vector<pair<int, int>>cntv; for (int i = 0; i < num; i++) { if (cntm.find(salaries[i]) != cntm.end()) { cntm[salaries[i]]++; } else { cntm[salaries[i]] = 1; posm[salaries[i]] = i; } } for (auto iter = cntm.begin(); iter != cntm.end(); iter++) { cntv.push_back(make_pair(iter->first, iter->second)); } /* sort(cntv.begin(), cntv.end(), [posm](const pair<int, int>&x, const pair<int, int>&y) ->int {return (x.second > y.second) || (x.second == y.second && posm.at(x.first) < posm.at(y.first)); }); */ sort(cntv.begin(), cntv.end(), [&posm](const pair<int, int>&x, const pair<int, int>&y) ->int {return (x.second > y.second) || (x.second == y.second && posm[x.first] < posm[y.first]); }); for (auto iter = cntv.begin(); iter != cntv.end(); iter++) { for (int i = 0; i < iter->second; i++) { res.push_back(iter->first); } } return res; }
發現將lambda的捕獲修改為[posm],即如下傳值就報錯:
sort(cntv.begin(), cntv.end(), [posm](const pair<int, int>&x, const pair<int, int>&y) ->int {return (x.second > y.second) || (x.second == y.second && posm[x.first] < posm[y.first]); });
報錯資訊如下:
但我這裡一開始宣告的posm不是const啊,怎麼回事?
原來是lambda表示式搞的鬼,當捕獲為map/unordered_map的值時,lambda表示式會預設轉換為const map/const unordered_map。但又為什麼會這樣轉換呢?
我查看了下C++標準:
map和unordered_map下的operator[],當關鍵字不存在則會進行插入,這樣當有關鍵字不存在時就會修改了posm的值,所以當捕獲為map/unordered_map的值時,lambda表示式乾脆預設轉換為const map/const unordered_map。這樣編譯器就會報錯了。
另外,當捕獲為map/unordered_map的值時,可以使用at(),即
sort(cntv.begin(), cntv.end(), [posm](const pair<int, int>&x, const pair<int, int>&y) ->int {return (x.second > y.second) || (x.second == y.second && posm.at(x.first) < posm.at(y.first)); });