#include <unordered_map>
#include <string>
#include <iostream>
#include <algorithm>
#include <utility>
int main()
{
std::unordered_map<string, int> hash {{"a", 1}, {"b", 2}, {"c", 3}};
// CaseA(NO-ERROR)
std::for_each(hash.begin(), hash.end(),
[](const std::pair<string, int>& p) {
std::cout << p.first << " => " << p.second << endl;
}
);
// CaseB(NO-ERROR)
std::for_each(hash.begin(), hash.end(),
[](const std::pair<string, int> p) {
std::cout << p.first << " => " << p.second << endl;
}
);
// CaseC(NO-ERROR)
std::for_each(hash.begin(), hash.end(),
[](std::pair<string, int> p) {
std::cout << p.first << " => " << p.second << endl;
}
);
// CaseD(ERROR)
std::for_each(hash.begin(), hash.end(),
[](std::pair<string, int>& p) {
std::cout << p.first << " => " << p.second << endl;
}
);
}
Q1&GT; 为什么CaseD错了?
Q2&GT; CaseA是推荐的方式吗?
谢谢
答案 0 :(得分:13)
value_type
的{{1}}为std::unordered_map<K,V>
(请注意std::pair<const K,V>
)。
您无法将类型为const
的引用绑定到类型为std::pair<K,V>
的对象。您应该使用std::pair<const K,V>
而不是直接拼写该类型的名称,因为这样可以确保您没有弄错。
如果您想知道,案例C的工作原理是因为有一个构造函数可以转换类型,因此std::unordered_map<K,V>::value_type
将是p
中值的副本。
对于不打算修改容器中元素的lambda的推荐方式是:
std::unordered_map
在问题的前3个案例中,完成了元素的复制(性能命中)。从调用者的角度来看,案例B和C是相同的(在一个函数中,顶级限定符被删除),但从lambda案例B的定义的角度来看,将确保你没有尝试修改参数(它本身就是源的副本)
答案 1 :(得分:5)
您的问题是您的容器已满std::pair<const string, int>
。对于案例1到3,容器中的std::pair<const string, int>
可以隐式转换为std::pair<string, int>
,然后临时传递给lambda。
C ++ 11中建议的方法是对容器的每个元素执行非变异操作:
for( auto const& p: hash ) {
std::cout << p.first << " => " << p.second << endl;
}
更简洁,并且不违反DRY。当有意义时,首选基于容器的迭代而不是基于迭代器的迭代。
在基于容器的std::
算法和auto
类型的lambda之间,使用std::
算法将在C ++的一个或两个版本中再次变得更具诱惑力。即便如此,除非你抽象使用lambda的算法,for_each
现在还很值得怀疑,因为我们有一流的语言功能可以完成for_each
的工作。