map<string,int> m;
string str;
while (cin >> str){
++m[str];
}
map<string, int>::const_iterator iter = m.begin();
while (iter != m.end()){
cout << iter->first << (iter++)->second << endl;
}
return 0;
上面是代码,但编译器给我一个关于无效解引用的错误,所以我 改变最后一行:
cout<<(iter++)->first<<iter->second<<endl;
我得到了正确的答案,我的问题是cout做了什么让我必须这样写,它是从后到前读取字符串吗?它是如何实现的? 或者我错了其他地方?
答案 0 :(得分:1)
&lt;&lt;运算符可以按任何顺序评估其操作数。在你的情况下,它可能在iter-&gt; first之前评估(iter ++) - &gt;秒。
你应该将你的iter ++放在下一行。
答案 1 :(得分:1)
您面临的问题是,有多种方法可以评估此问题。问题是每个 operator<<
可以在其右侧之前评估其左侧,反之亦然。由于你有三个,可能有很多变种。
现在,您尝试使用iter
两次,并在一个语句中修改它,而没有任何序列。这使它成为未定义的行为。任何事情都可能发生。
修复:使用两个语句。语句以明显的顺序排序。
答案 2 :(得分:1)
如果表达式为a << b
,则必须同时评估a
和b
,但是未评估它们的评估顺序,这意味着允许任何顺序({{1首先,a
首先,两者同时以某种方式)。
当链接多个这样的表达式时也是如此,例如b
。
实际上,重载运算符是作为函数调用实现的。例如
a << b << c
可能会扩展到类似
的内容std::cout << iter->first << (iter++)->second; // drop << endl for simplicity of discussion
函数参数的评估顺序也未指定。因此,在将operator<<(operator<<(std::cout << iter->first), (iter++)->second);
和operator<<(std::cout << iter->first)
传递给(iter++)->second)
的最外层调用之前,评估operator<<()
和(iter++)->second)
的顺序。
您的编译器恰好会在operator<<(std::cout << iter->first)
之前评估iter
,即使您期望相反。
解决方案不是在一个陈述中混合太多操作和副作用,因为这是一个很好的方法来解决这些排序问题。在您的情况下,执行输出,并在下一个语句中增加cout << iter->first << iter->second << endl;
++iter;
。
SELECT * FROM post WHERE writtenday >= 25;