简体   繁体   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;

above is the code,but compiler give me a error about invalid dereference,so I change last line like that: 上面是代码,但是编译器给我一个关于无效解除引用的错误,因此我更改了最后一行:

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

and I got right answer,my question is what cout have done make me have to write like this,Is it read string from back to front?how does it implement? 我得到正确的答案,我的问题是cout做了什么使我不得不这样写,它是从头到尾读取字符串吗?它是如何实现的? or am I wrong other place? 还是我错在其他地方?

The << operator can evaluate its operands in any order. <<操作符可以按任何顺序求值。 In your case it probably evaluated (iter++)->second before iter->first. 在您的情况下,它可能在iter-> first之前评估(iter ++)->第二。

You should put your iter++ at the next line. 您应该将iter ++放在下一行。

The problem you're facing is that there are multiple ways in which this can be evaluated. 您面临的问题是可以通过多种方式对其进行评估。 The problem is that each operator<< can evaluate its left side before its right side or vice versa. 问题是每个 operator<<可以先评估左侧,然后评估右侧,反之亦然。 And since you have three, there are quite a few variants possible. 并且由于您有三个,因此有很多变体。

Now you're trying to use iter twice, and also modify it, in one statement, without anything to sequence that. 现在,您尝试使用一次iter ,并在一条语句中对其进行修改,而无需进行任何排序 That makes it Undefined Behavior. 这使其成为未定义行为。 Anything may happen. 可能发生任何事情。

Fix: use two statements. 修正:使用两个语句。 Statements are sequenced in the obvious order. 语句以明显的顺序排序。

Given an expression of the form a << b , a and b must both be evaluated, but the order they are evaluated is unspecified, which means any order is permitted ( a first, b first, both concurrently somehow). 给出的形式的表达a << bab必须都被评估,但它们的计算顺序是不确定的,这意味着任何顺序被允许( a第一, b第一,两者同时以某种方式)。

The same goes when multiple such expressions are chained, such as a << b << c . 当多个这样的表达式链接在一起时,例如a << b << c ,也是如此。

Practically, overloaded operators are implemented as function calls. 实际上,重载运算符实现为函数调用。 For example 例如

std::cout << iter->first << (iter++)->second;   // drop  << endl for simplicity of discussion

may be expanded to something like 可能会扩展为类似

operator<<(operator<<(std::cout << iter->first), (iter++)->second);

The order of evaluation of function arguments is also unspecified. 函数参数的求值顺序也未指定。 So the order of evaluating operator<<(std::cout << iter->first) and (iter++)->second) before passing them to the outermost call of operator<<() . 因此,在将operator<<(std::cout << iter->first)(iter++)->second)传递给operator<<()的最外层调用之前,求值顺序。

It just so happens with your compiler that (iter++)->second) is evaluated before operator<<(std::cout << iter->first) , even though you were expecting the opposite. 即使您期望相反,编译器也是如此,它会在operator<<(std::cout << iter->first)之前评估(iter++)->second)

The solution is not to mix too many operations with side effects in one statement, because that is a good way to trip over such ordering concerns. 解决方案是不要在一个语句中混合太多的操作和副作用,因为这是解决此类排序问题的好方法。 In your case, do the output, and increment iter in the next statement. 根据您的情况,执行输出,然后在下iter语句中增加iter

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

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

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