zoukankan      html  css  js  c++  java
  • 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)); });
  • 相关阅读:
    深入浅出java的Map
    退役划水(7)
    .NET 云原生架构师训练营(模块二 基础巩固 EF Core 关系)--学习笔记
    .NET 云原生架构师训练营(模块二 基础巩固 EF Core 基础与配置)--学习笔记
    .NET 云原生架构师训练营(模块二 基础巩固 EF Core 介绍)--学习笔记
    .NET 云原生架构师训练营(模块二 基础巩固 MySQL环境准备)--学习笔记
    .NET 云原生架构师训练营(模块二 基础巩固 MVC终结点)--学习笔记
    .NET 云原生架构师训练营(模块二 基础巩固 路由与终结点)--学习笔记
    .NET 云原生架构师训练营(模块二 基础巩固 HTTP管道与中间件)--学习笔记
    .NET 云原生架构师训练营(模块二 基础巩固 REST && RESTful)--学习笔记
  • 原文地址:https://www.cnblogs.com/a3192048/p/12241294.html
Copyright © 2011-2022 走看看