2013-06-18 35 views
2

說我有這個功能的語句代碼風格:如果與回報

inline bool fileExists(const char *name) { 
    FILE *file; 
    if (fopen_s(&file, name, "r") == 0) 
    { 
    fclose(file); 
    return true; 
    } else { 
    return false; 
    } 
} 

更好做上述一個或這一個?

inline bool fileExists(const char *name) { 
    FILE *file; 
    if (fopen_s(&file, name, "r") == 0) 
    { 
    fclose(file); 
    return true; 
    } 

    return false; 
} 

編譯時是否有區別?

+1

不,生成的代碼將與任何**體面編譯器**(在發佈版本中)完全相同。一個可怕的編譯器可能會爲else分支發出一個額外的跳轉。 –

+0

可能有一點小差異,但你不會注意到它,在這裏談論納秒。 –

回答

6

這主要是一個意見問題。海事組織第二種形式更好,因爲它將始終提供回報價值。如果修改該函數以在else子句中執行不同的操作,則可以忘記添加返回值。在上面的示例中,生成的代碼是相同的。

4

效率不是問題,沒有。一個體面的編譯器會知道該怎麼做。對於這個簡單的功能,邏輯上它應該是相同的。對於更大的功能,雖然有更多的邏輯,第二個稍微好一點,因爲它保證了函數總是返回。

要麼是這樣,要麼是偏好單點回報(但這並不一定適用於此,但功能相對較小)。這可以幫助編譯器生成更好的,更有效的代碼,在某些情況下(多return語句阻礙RVO):

inline bool fileExists(const char *name) { 
    FILE *file; 
    bool exists = false; 
    if (fopen_s(&file, name, "r") == 0) 
    { 
    fclose(file); 
    exists = true; 
    } 
    return exists; 
} 
+2

儘管多年來一直主張「單點回報」,但我認爲(和AFAICT並非唯一),它通常會通過增加縮進級別並將變量保持在太長時間內而降低可讀性。我傾向於選擇「提前回歸」(就像在OP的第二個片段中所做的那樣),即在函數開始時擺脫不尋常的路徑,然後繼續主要行爲。儘管如此,關於RVO的爭論仍然存在。 –

+0

@LucTouraille當然是個案情況。我不是「永遠」規則的粉絲。 –

1

沒有,編譯器的語義analyis,也是優化後,將導致相同的目標代碼。

1

在這種特殊情況下,絕對不是問題。 fopen將需要幾微秒(除非實際文件的目錄沒有被緩存,在這種情況下,它是幾毫秒),並且您擔心會有一次額外的跳躍 - 這可能是4-6個時鐘週期。

一般而言,我更喜歡「一個回報聲明」,但它有時會變得相當混亂,在這種情況下,我更喜歡第二個選項。幾乎總是,代碼會變成這樣的事情,作爲「編譯」,也喜歡一個出口點:

bool fileExists(const char *name) { 
    FILE *file; 
    bool ret_val; 
    if (fopen_s(&file, name, "r") == 0) 
    { 
    fclose(file); 
    ret_val = true; 
    goto end; 
    } 
    ret_val = false 
end: 
    return ret_val; 
} 

有時候,如果代碼是非常複雜的 - 尤其是如果代碼是「簡單的開始」,並然後變得複雜,編譯器將有一個函數的多個返回點,但上面的場景是相當典型的。 [我不建議你在你的代碼中使用goto'。編譯器是完全有能力做出差異]

哦,我懷疑在這種情況下使用inline是不會真的在性能上有太大的區別。

+0

內聯可能會阻止多個定義。 –

+0

當然,但我也沒有看到將它放在標題中的很多觀點 - 與實際打開文件的開銷相比,在進行內聯時節省很少 - 並且假設它與系統中的其他名稱相沖突應該使用不同的名稱。 –

+0

Ops,我忘了靜態內聯...我的功能只存在於一個.cpp文件中。 – LppEdd