関数から空の文字列を返す方法は2つあります。
1)
std::string get_string()
{
return "";
}
2)
std::string get_string()
{
return std::string();
}
どちらがより効率的で、なぜですか?
Gcc 7.1 -O3これらはすべて同一です、godbolt.org/z/a-hc1d – jterm Apr 25 at 3:27
いくつか掘りましたか?以下は、サンプルプログラムと関連するアセンブリです。
コード:
#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::string
とreturn {};
にはほとんどないことがわかります(これら2つは同じです)。
Frerich Raabeが言ったように、空のC_string
を渡すときは、単にメモリを割り当てるのではなく、それを処理する必要があります。これは(少なくともGCCではなく)最適化することはできないようです
だから答えは間違いなく使用することです:
return std::string();
または
return {}; //(c++11)
ただし、パフォーマンスが重要なコード(おそらくログに記録されますか?)で大量の空の文字列を返さない限り、違いはわずかです。
後者のバージョンが最初のバージョンより遅くなることはありません。最初のバージョンは、C文字列を取得するstd::string
コンストラクターを呼び出します。このコンストラクターは、最初に文字列の長さを計算する必要があります。空の文字列を処理するのは高速ですが、まったく実行しないよりは確実に高速ではありません。