关于c ++的ostream

时间:2015-10-12 13:07:49

标签: c++ iterator cout

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做了什么让我必须这样写,它是从后到前读取字符串吗?它是如何实现的? 或者我错了其他地方?

3 个答案:

答案 0 :(得分:1)

&lt;&lt;运算符可以按任何顺序评估其操作数。在你的情况下,它可能在iter-&gt; first之前评估(iter ++) - &gt;秒。

你应该将你的iter ++放在下一行。

答案 1 :(得分:1)

您面临的问题是,有多种方法可以评估此​​问题。问题是每个 operator<<可以在其右侧之前评估其左侧,反之亦然。由于你有三个,可能有很多变种。

现在,您尝试使用iter两次,并在一个语句中修改它,而没有任何序列。这使它成为未定义的行为。任何事情都可能发生。

修复:使用两个语句。语句以明显的顺序排序。

答案 2 :(得分:1)

如果表达式为a << b,则必须同时评估ab,但是未评估它们的评估顺序,这意味着允许任何顺序({{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;