简体   繁体   中英

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? 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.

You should put your iter++ at the next line.

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. 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. 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).

The same goes when multiple such expressions are chained, such as 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<<() .

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.

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.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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