繁体   English   中英

关于C ++的OStream

[英]About ostream of c++

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做了什么使我不得不这样写,它是从头到尾读取字符串吗?它是如何实现的? 还是我错在其他地方?

<<操作符可以按任何顺序求值。 在您的情况下,它可能在iter-> first之前评估(iter ++)->第二。

您应该将iter ++放在下一行。

您面临的问题是可以通过多种方式对其进行评估。 问题是每个 operator<<可以先评估左侧,然后评估右侧,反之亦然。 并且由于您有三个,因此有很多变体。

现在,您尝试使用一次iter ,并在一条语句中对其进行修改,而无需进行任何排序 这使其成为未定义行为。 可能发生任何事情。

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

给出的形式的表达a << bab必须都被评估,但它们的计算顺序是不确定的,这意味着任何顺序被允许( 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<<()的最外层调用之前,求值顺序。

即使您期望相反,编译器也是如此,它会在operator<<(std::cout << iter->first)之前评估(iter++)->second)

解决方案是不要在一个语句中混合太多的操作和副作用,因为这是解决此类排序问题的好方法。 根据您的情况,执行输出,然后在下iter语句中增加iter

cout << iter->first << iter->second << endl;
++iter;

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM