[英]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 << b
, a
和b
必须都被评估,但它们的计算顺序是不确定的,这意味着任何顺序被允许( 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.