1. 程式人生 > >C++11 lambda表示式不能捕獲map/unordered_map值

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