首頁 > 後端開發 > C++ > `i = i` 是否會在 C 中呼叫使用者定義類型的未定義行為?

`i = i` 是否會在 C 中呼叫使用者定義類型的未定義行為?

Mary-Kate Olsen
發布: 2024-12-05 10:36:15
原創
816 人瀏覽過

Does `i  =   i` Invoke Undefined Behavior with User-Defined Types in C  ?

重新審視未定義行為:序列點和用戶定義類型

問題:

在上一篇關於未定義行為和序列點的文章中,表達式i = i 被認為是呼叫內建類型的未定義行為。然而,問題來了:如果 i 的類型是使用者定義的怎麼辦?具體來說,假設我們有一個帶有重載運算子的 Index 類別。

答案:未定義的行為與明確定義的行為

與直覺相反,事實證明,表達式i = i 不會調用Index 等用戶定義類型的未定義行為。這是因為 Index 中的重載運算子被視為函數。根據 C ISO 標準,函數求值在函數參數求值後引入一個序列點,複製回傳值後再引入另一個序列點。

序列點和重載運算子

在 i = i 的情況下,表達式 i 在作為參數傳遞給運算子 = 之前先進行計算。這表示在對 i 求值之後存在一個序列點,確保物件 i 在連續的序列點之間僅被修改一次。

因此,表達式i = i 對於使用者定義類型(如Index)是等效的編寫i.operator =(i.operator ()); ,這是一個定義良好的表達式,沒有未定義的行為。這同樣適用於語法上較簡單的表達式 i.add(i.inc());。

微妙的區別:

重要的是要注意 i = i 不是 C 語法意義上的表達式。相反,它是一個“語句表達式”,它是表達式和語句的語法組合。語句表達式與普通語句一樣執行,但其結果也可以賦值給變數。

a[ i] = i

如果a 是陣列對於內建類型,表達式a[ i] = i 會呼叫未定義的行為,因為左值a[ i] 被求值兩次:一次在表達式i 中,另一次在賦值i = 中i.

但是,如果 a是重載下標運算子的使用者定義類型,則表達式的行為可能會有所不同,具體取決於下標運算子的實作。例如,如果使用 const Index& operator[](Index i) 實作下標運算符,則表達式將是明確定義的,因為在呼叫下標運算子之前,左值 a[ i] 僅計算一次。

i 的有效性;

表達式 i;在 C 03 中定義良好,因為它等價於 ((i.operator ()).operator ()).operator ()。這是因為每個運算子引入了一個序列點,確保物件 i 在連續的序列點之間僅被修改一次。

以上是`i = i` 是否會在 C 中呼叫使用者定義類型的未定義行為?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
作者最新文章
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板