About ostream of c++

About ostream of c++

本文关键字:c++ of ostream About      更新时间:2023-10-16
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;

我得到了正确的答案,我的问题是我做了什么让我不得不这样写,它是从后到前读取字符串吗?它是如何实现的?还是我错在别的地方了?

给定一个形式为a << b的表达式,ab必须同时求值,但求值的顺序不指定,即允许任意顺序(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;

first之前计算(iter++)->second。

你应该把iter++放在下一行

您面临的问题是,有多种方法可以对其进行评估。问题是每个 operator<<都可以在计算其左侧之前计算右侧,反之亦然。既然你有三个,就有很多可能的变体。

现在你试图使用iter两次,并修改它,在一个语句中,没有任何序列。这就是未定义行为。一切皆有可能。

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