我有一个set<pair<string,map<string,int> > > setLabelsWords;
这个类的成员变量,这个变量有点令人费解,但我要忍受。在同一个类的成员函数中,我有以下代码:
pair<map<string,int>::iterator,bool> ret;
for (auto j:setLabelsWords) {
if (j.first == label) {
for (auto k:words) {
ret = j.second.insert(make_pair(k,1));
if (ret.second == false) {
j.second[k]++;
}
}
}
}
&#34;也就是说&#34;是一组字符串和&#34;标签&#34;是一个字符串。所以基本上它应该插入&#34; k&#34; (一个字符串)并且如果k已经在地图中,它将int递增1.问题是它是有效的,直到最外面的for循环结束。如果我在最后一个括号之前打印j.second的大小,它会给我一个我期望的大小为13的大小,但是在最后一个大括号之外,大小会回到7,这就是地图的大小是最初在此代码块运行之前。我非常困惑,为什么会发生这种情况,我们非常感谢任何帮助。
答案 0 :(得分:4)
for (auto j:setLabelsWords) {
这会按容器 按值 进行迭代。这与你做的一样:
class Whatever { /* something in here */ };
void changeWhatever(Whatever w);
// ...
{
Whatever w;
changewhatever(w);
}
无论changewhatever
对w
做了什么,无论做了什么修改,都会对w
的副本进行修改,因为它会通过值传递给函数。
为了正确更新容器,您必须按引用进行迭代:
for (auto &j:setLabelsWords) {
答案 1 :(得分:2)
for (auto j:setLabelsWords) {
这会为每个元素创建副本。您在j
上执行的所有操作都会影响该副本,而不会影响setLabelsWords
中的原始元素。
通常情况下,您只需使用参考:
for (auto&& j:setLabelsWords) {
但是,由于std::set
的性质,这不会让你走得太远,因为std::set
的元素不能通过迭代器或元素引用自由修改,因为这样可以你要创建一个包含重复项的集合。编译器不允许这样做。
这是一个实用的解决方案:使用std::vector
代替std::set
:
std::vector<std::pair<std::string, std::map<std::string,int>>> setLabelsWords;
然后,您将能够使用上述的参考方法。
如果您稍后需要std::set
的唯一性和排序功能,则可以在std::sort
上应用std::unique
和/或std::vector
,或者创建新{来自std::set
元素的{1}}。