簡體   English   中英

是 std::cin >> i >> ++i; 未定義的行為

[英]Is std::cin >> i >> ++i; undefined behavior

我試圖了解 C++ 中表達式的評估順序。 我有以下示例:

int i = 0;
std::cin >> i >> i; //IS THIS UB? 

我的第一個問題是上面顯示的片段是否會產生 UB?

下一個,

int i = 0;
std::cin >> i >> ++i; //IS THIS UB?

我的第二個問題是這個片段會產生 UB 嗎?

std::cin >> i >> i; 是並且一直是明確定義的。

std::cin >> i >> ++i; 現在定義明確,但 UB pre-C++17。

這種 UB 是對同一標量的未排序寫入或相對於同一標量的讀取未排序的寫入引起的。

std::cin >> i >> i; ,即使i被修改了兩次(在重載的>>內),第一次修改在第二次修改之前排序。 第一個>>的返回值必須首先計算,作為參數傳遞給第二個>> ,因此必須按此順序調用它們。 請參見此處的規則 (3)

std::cin >> i >> ++i; ,另一方面,在 C++17 之前,相對於讀取 ( i ) 存在未排序的寫入 ( ++i ),從而導致 UB。 但是在 C++17 和更新版本中, >><<總是在 rhs 之前計算 lhs,導致i++i之前排序,請參見此處的規則 (19)

案例一

在這種情況下, std::cin >> i >> i; 可以寫成(或等價於):

std::cin.operator>>(i).operator>>(i);

這里有兩件重要的事情需要考慮

  1. std::cin::operator>>通過引用返回cin object
  2. 每次調用std::cin>>operator>>都保證按從左到右的順序進行。

所以在這種情況下沒有未定義的行為。

案例二

在這種情況下, std::cin >> i >> ++i; 可以寫成(或等價於):

std::cin.operator>>(i).operator>>(++i);

現在,從第 1.9 節第 16 點開始:

When calling a function (whether or not the function is inline), there is a sequence point after the evaluation of all function arguments (if any) which takes place before execution of any expressions or statements in the function body. 在復制返回值之后和執行 function 之外的任何表達式之前,還有一個序列點。

但請注意,上述引用聲明僅保證:

  1. i在第一次調用operator>>之前被評估,並且
  2. ++i在第二次調用operator>>之前進行評估。

但是引用並不能保證i++i之前被評估,反之亦然。 這意味着計算i++i的順序是未定義的,因此在這種情況下生成的代碼將具有未定義的行為

以上討論適用於Pre-C++11 ,因為 OP 沒有標記 C++11。

暫無
暫無

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

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