[英]C++ Language Parsing and Logical Operators's Short-Circuit
當涉及到邏輯運算符的短路時,根據 7.6.14 e 7.6.15 (N4868) 中的標准。
7.6.14 邏輯與運算符
[...] 如果第一個操作數為假,則不會評估第二個操作數。
7.6.15 邏輯或運算符
[...] 如果第一個操作數的計算結果為真,則不會計算第二個操作數。
當此實現在邏輯運算符鏈接中討論為 (Cond1 && Cond2 && Cond3) 時,在我的解釋中,所呈現的與我目前的心理 model不同,關於 c++ 代碼解析/運算符綁定如何發生在編譯器時。
對於某些東西
if (cond1 && cond2 && cond3) {
//something
}
理解為“如果cond1為假,則發生短路,cond2和cond3不求值,表達式為假” 。
對我來說,即使你有相同的結果,關於解析應該如何工作的更准確的表達是“第一個'AND'操作是第二個的子表達式。如果 cond1 為假,則發生短路,cond2不計算,子表達式被計算為假。然后在第二個操作中發生短路,cond3 沒有被計算,這個表達式也被計算為假”。
喜歡:
(cond1 && cond2) && cond3: 評估 cond1 並將子表達式短路為 false (不評估 cond2)
false && cond3:將完整表達式短路為 false(未評估 cond3)
我擔心像 C ++ 這樣的高級語言中的 model 而不是運行時的實現(編譯器的實現似乎與我展示的第一個表達式完全相同,如果 cond1 為 false 則發生跳轉)。
我所做的解釋是准確的,迂腐的還是不正確的,在這種情況下不合適(這是過度思考)?
就編譯器的“心理模型”而言,您是正確的,而在這種特定情況下,就 CPU 的“心理模型”而言,寫“如果cond1
為假,則完整表達式為false
”的人是正確的。
在編譯器方面,解析cond1 && cond2 && cond3
結果(使用 clang -ast-dump
)
`-BinaryOperator 0x557a79f02230 <col:1, col:19> 'bool' '&&'
|-BinaryOperator 0x557a79f021d8 <col:1, col:10> 'bool' '&&'
| |-ImplicitCastExpr 0x557a79f021a8 <col:1> 'bool' <LValueToRValue>
| | `-DeclRefExpr 0x557a79f02168 <col:1> 'bool' lvalue Var 0x557a79f01da0 'cond1' 'bool'
| `-ImplicitCastExpr 0x557a79f021c0 <col:10> 'bool' <LValueToRValue>
| `-DeclRefExpr 0x557a79f02188 <col:10> 'bool' lvalue Var 0x557a79f01ec8 'cond2' 'bool'
`-ImplicitCastExpr 0x557a79f02218 <col:19> 'bool' <LValueToRValue>
`-DeclRefExpr 0x557a79f021f8 <col:19> 'bool' lvalue Var 0x557a79f01fa8 'cond3' 'bool'
對這棵樹的評估從第 19 列的根&&
開始,它必須首先評估它的 lhs: 所以它走到第 10 列的&&
,它也必須首先評估它的 lhs: 所以它走到cond1
。 如果返回false
, col:10 &&
也返回false
,而不訪問 rhs 分支,然后 col:19 &&
也返回false
而不訪問 rhs 分支。
我剛剛測試的 gcc 和 clang 都生成了相當於
if (cond1 == false) goto done;
if (cond2 == false) goto done;
if (cond3 == false) goto done;
return true;
done:
return false;
所以這個評估是一個(非常簡單的)編譯器優化的例子
有關 AST 和編譯代碼,請參見https://godbolt.org/z/rYc11PvPb
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.