2014-10-27 27 views
9

我有2種方法從函數返回一個空字符串。返回空字符串:有效的方式在c + +

1)

std::string get_string() 
{ 
    return ""; 
} 

2)

std::string get_string() 
{ 
    return std::string(); 
} 

哪一個更有效,爲什麼呢?

+12

也沒有。使用'return {};'。 – 2014-10-27 12:00:50

+2

這和C有什麼關係? – crashmstr 2014-10-27 12:01:18

+3

這屬於無用的微優化領域,您的編譯器將使用RVO和複製elision優化。 – CoryKramer 2014-10-27 12:01:29

回答

19

做了一些挖掘。下面是一個例子程序和相關組件:

代碼:

#include <string> 

std::string get_string1(){ return ""; } 

std::string get_string2(){ return std::string(); } 

std::string get_string3(){ return {}; }   //thanks Kerrek SB 

int main() 
{ 
    get_string1(); 
    get_string2(); 
    get_string3(); 
} 

大會:

__Z11get_string1v: 
LFB737: 
    .cfi_startproc 
    pushl %ebx 
    .cfi_def_cfa_offset 8 
    .cfi_offset 3, -8 
    subl $40, %esp 
    .cfi_def_cfa_offset 48 
    movl 48(%esp), %ebx 
    leal 31(%esp), %eax 
    movl %eax, 8(%esp) 
    movl $LC0, 4(%esp) 
    movl %ebx, (%esp) 
    call __ZNSsC1EPKcRKSaIcE 
    addl $40, %esp 
    .cfi_def_cfa_offset 8 
    movl %ebx, %eax 
    popl %ebx 
    .cfi_restore 3 
    .cfi_def_cfa_offset 4 
    ret $4 
    .cfi_endproc 

__Z11get_string2v: 
LFB738: 
    .cfi_startproc 
    movl 4(%esp), %eax 
    movl $__ZNSs4_Rep20_S_empty_rep_storageE+12, (%eax) 
    ret $4 
    .cfi_endproc 

__Z11get_string3v: 
LFB739: 
    .cfi_startproc 
    movl 4(%esp), %eax 
    movl $__ZNSs4_Rep20_S_empty_rep_storageE+12, (%eax) 
    ret $4 
    .cfi_endproc 

這與-std=c++11 -O2編譯。

您可以看到return "";聲明中有相當多的工作,而return std::stringreturn {};(這兩個是相同的)聲明的工作量相當少。

正如Frerich拉貝說,傳遞一個空C_string時,它仍然需要做就可以處理,而不是僅僅分配內存。看來,這不能被優化掉(至少不是通過GCC)

因此,答案是明確地使用:

return std::string(); 

return {}; //(c++11) 

雖然,除非你正在返回很多性能關鍵代碼中的空字符串(記錄我猜?),差異將仍然是微不足道的。

+0

也許這需要2017年的更新所有這三種可能性返回產生相同的結果,所以沒有關於返回「」或std :: string {}或{}的問題。測試編譯器資源管理器中的叮噹聲和gcc – 2017-07-19 10:53:18

+0

@TomazCanabrava我當時應該注意到gcc版本...如果你想提供你測試過的叮聲音和gcc版本,我會在答案中註明這一點。 – Baldrickk 2017-07-19 12:19:48

+0

@TomazCanabrava實際上,當我用上面的方法嘗試gcc和clang時,我得到了類似的結果(gcc 7.1/clang4.0.0)。有趣的是,Visual Studio(2015)提供了每個版本之間一致的結果,但是在所有情況下都會有更多的工作。 – Baldrickk 2017-07-19 12:50:30

3

後者的版本永遠不會比第一版慢。第一個版本調用std::string構造函數獲取C字符串,然後必須首先計算字符串的長度。即使這對於一個空字符串來說很快,但它肯定不會比完全不這樣做更快。

+0

由於它是一個常量被返回,編譯器沒有對長度計算進行優化嗎?如果不是,可能嗎? – Baldrickk 2014-10-27 12:06:49

+0

@Baldrickk他正在調用'std :: string'的一個參數構造函數。我不認爲有很多(如果有的話)編譯器足夠聰明,可以推斷出一個參數構造函數等價於構造函數同時攜帶一個指針和一個大小,前提是它傳遞一個小於字符串大小的值文字(後面有''\ 0')。 – 2014-10-27 12:23:23

+0

@JamesKanze:有些編譯器在字符串文字上優化'strlen()' - 我要求在十多年前將該功能添加到SparcWorks C++中 - 不知道他們是否曾經這麼做 - GCC已經做到了。儘管如此 - 我不一定會期望C++實現使用'strlen' ......但永遠不會知道。 – 2014-10-27 12:54:31