簡體   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;

上面是代碼,但是編譯器給我一個關於無效解除引用的錯誤,因此我更改了最后一行:

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

我得到正確的答案,我的問題是cout做了什么使我不得不這樣寫,它是從頭到尾讀取字符串嗎?它是如何實現的? 還是我錯在其他地方?

<<操作符可以按任何順序求值。 在您的情況下,它可能在iter-> first之前評估(iter ++)->第二。

您應該將iter ++放在下一行。

您面臨的問題是可以通過多種方式對其進行評估。 問題是每個 operator<<可以先評估左側,然后評估右側,反之亦然。 並且由於您有三個,因此有很多變體。

現在,您嘗試使用一次iter ,並在一條語句中對其進行修改,而無需進行任何排序 這使其成為未定義行為。 可能發生任何事情。

修正:使用兩個語句。 語句以明顯的順序排序。

給出的形式的表達a << bab必須都被評估,但它們的計算順序是不確定的,這意味着任何順序被允許( 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語句中增加iter

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM