2012-04-17 30 views
2

考慮我的評價如下:「如果」表達式

edge some_edge; 
std::priority_queue<edge> my_queue; 

是否安全,寫出這樣的「如果」,即使隊列可能是空的?

if ((my_queue.size() > 0) && (my_queue.top().weight < some_edge.weight)) { 
    do_something; 
} 

這個呢?

if ((my_queue.top().weight < some_edge.weight) && (my_queue.size() > 0)) { 
    do_something; 
} 

是否評估表達式中'和'是操作符之間的運算符停止如果左操作數計算結果爲false?

+1

'if'是C++語句,不是表達式。是的,C++需要進行短路評估(只要不涉及重載的'operator &&'或'operator ||')。 – ildjarn 2012-04-17 18:30:30

+0

但是我們正在談論的關於在這種情況下評估的東西是表達式@Ildjarn。他們在「if」陳述內的事實實際上並不相關。 – 2012-04-17 18:32:39

回答

4

在C++中if語句從左到右聯想和邏輯布爾運算符&&||是短路,所以是的,因爲這是保證您先檢查大小類似下面的語句是安全的(假設沒有邪惡這些運營商的)超載:

if(myqueue.size() > 0 && myqueue.top().whatever) { 
    // ... 
} 

相反的是不正確卻因你檢查的size()返回值後彈出隊列。

順便說一下,std::priority_queue提供了empty()函數,我/許多人寧願優於size() > 0,但這也起作用。

if(!myqueue.empty() && myqueue.top().whatever()) { 
    // ... 
} 
+0

國際海事組織,它會更好*不*在此提及相關性 - 評估順序不是由結合性決定,而是由序列點決定。 – 2012-04-17 19:14:41

3

是的,這種行爲是保證每個C++標準。

if (false && doSomething()) 

永遠不會評估doSomething()

但是,如果您重載operator&&,則會評估所有表達式,因此此行爲可能會有所不同。這就是觸摸operator&&的原因。您可以使用!empty()而不是size() > 0

0

布爾表達式被短路評估,所以如果第一部分失敗,第二部分將不會運行。所以第一個例子不會訪問不敏感的內存,但第二個例子會。

2

這真的不是關於if根本就是關於&&。邏輯運算符(&&||)首先評估它們的左操作數。那麼當且僅當右操作數可能影響邏輯結果時,纔會評估右操作數。

&&的情況下,如果左操作數的計算結果爲false,則結果將爲false,而不管右操作數的值如何,因此不會評估右操作數。

||的情況下,如果左操作數的計算結果爲true,其結果將是true無論右操作數的值,所以正確的操作將不被計算。

無論&&是否在if聲明的表達式中,情況都是如此。一些混淆代碼將​​轉換爲x && y。雖然沒有經常看到,但您也可以||一樣。

+0

好吧,它*是關於'if'語句的,因爲它必須保證從左到右執行才能工作,但是,對於短路更多。 – 2012-04-17 19:06:53

+0

@EdS .:關鍵是'if'只是評估一個表達式。表達式本身強制執行從左到右的評估,而不管它是否在'if'語句中。 – 2012-04-17 19:07:48

+0

的確如此。 [字符] – 2012-04-17 19:10:00