我使用MinGW(TDM)編譯它4.8 .1帶有選項-fdump-tree-optimized,不帶-O2
第一個做這樣
string tmp = a+b; // that mean create new string g, g += b, tmp = g (+dispose g)
tmp += c;
return tmp; // and dispose tmp
的移動第二做另一種說法
string tmp = a; // just copy a to tmp
tmp += b;
tmp += c;
return tmp; // and dispose tmp
它看起來就像這樣
void * D.20477;
struct basic_string D.20179;
<bb 2>:
D.20179 = std::operator+<char, std::char_traits<char>, std::allocator<char> > (a_1(D), b_2(D)); [return slot optimization]
*_3(D) = std::operator+<char, std::char_traits<char>, std::allocator<char> > (&D.20179, c_4(D)); [return slot optimization]
<bb 3>:
<bb 4>:
std::basic_string<char>::~basic_string (&D.20179);
D.20179 ={v} {CLOBBER};
<L1>:
return _3(D);
<L2>:
std::basic_string<char>::~basic_string (&D.20179);
_5 = __builtin_eh_pointer (1);
__builtin_unwind_resume (_5);
和
void * D.20482;
struct string r [value-expr: *<retval>];
<bb 2>:
std::basic_string<char>::basic_string (r_1(D), a_2(D));
std::basic_string<char>::operator+= (r_1(D), b_3(D));
<bb 3>:
std::basic_string<char>::operator+= (r_1(D), c_4(D));
<bb 4>:
<L0>:
return r_1(D);
<L1>:
std::basic_string<char>::~basic_string (r_1(D));
_5 = __builtin_eh_pointer (1);
__builtin_unwind_resume (_5);
所以,應用-O2優化後n編譯器將ConcatB函數保持在幾乎相同的視圖中,並通過內聯函數,向內存分配部分添加常量值,聲明新函數,但最有價值的部分保持不變。
ConcatA:
D.20292 = std::operator+<char, std::char_traits<char>, std::allocator<char> > (a_2(D), b_3(D)); [return slot optimization]
*_5(D) = std::operator+<char, std::char_traits<char>, std::allocator<char> > (&D.20292, c_6(D));
ConcatB:
std::basic_string<char>::basic_string (r_3(D), a_4(D));
std::basic_string<char>::append (r_3(D), b_6(D));
std::basic_string<char>::append (r_3(D), c_8(D));
所以,很明顯,ConcatB比ConcatA更好,因爲它確實少分配操作,這是當你想非常昂貴優化這些小代碼。
如何循環兩個單獨的10,000次並比較差異? –
儘管'ConcatA'構造了多個字符串,但它可能比'ConcatB'更快,因爲第二個字段可能會有額外的重新分配和複製。 –
當產生這樣的連接時,源範圍中的「連接視圖」可以提供體面的性能優勢(甚至可以避免創建連接字符串)。這種連接的一個例子是'boost :: range :: join'(http://www.boost.org/doc/libs/1_55_0/libs/range/doc/html/range/reference/utilities/join.html ;它只需要2個源代碼範圍,但可以用C++ 11進行真正的多範圍連接。 – oakad