关于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++)->second
你应该把你的 iter++ 放在下一行。
您面临的问题是可以通过多种方式对其进行评估。问题是 each operator<<
可以先评估其左侧,然后再评估其右侧,反之亦然。由于您拥有三个,因此可能有很多变体。
现在您尝试使用 iter
两次,并在一个语句中对其进行修改,而不对 sequence 进行任何操作。这使它成为未定义的行为。什么事都有可能发生。
修复:使用两个语句。语句按明显的顺序排列。
给定 a << b
形式的表达式,a
和 b
都必须求值,但它们求值的顺序是未指定的,这意味着任何顺序都是允许的(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
。
cout << iter->first << iter->second << endl;
++iter;
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++)->second你应该把你的 iter++ 放在下一行。
您面临的问题是可以通过多种方式对其进行评估。问题是 each operator<<
可以先评估其左侧,然后再评估其右侧,反之亦然。由于您拥有三个,因此可能有很多变体。
现在您尝试使用 iter
两次,并在一个语句中对其进行修改,而不对 sequence 进行任何操作。这使它成为未定义的行为。什么事都有可能发生。
修复:使用两个语句。语句按明显的顺序排列。
给定 a << b
形式的表达式,a
和 b
都必须求值,但它们求值的顺序是未指定的,这意味着任何顺序都是允许的(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
。
cout << iter->first << iter->second << endl;
++iter;