2017-09-06 30 views
10

大多數std::string實現(包括GCC)使用小字符串優化。例如。有一個answer討論這一點。gcc沒有小字符串優化?

今天,我決定檢查我編譯的代碼中的一個字符串被移到堆中的哪一點。令我驚訝的是,我的測試代碼似乎顯示根本沒有發生小字符串優化!

代碼:

#include <iostream> 
#include <string> 

using std::cout; 
using std::endl; 

int main(int argc, char* argv[]) { 
    std::string s; 

    cout << "capacity: " << s.capacity() << endl; 

    cout << (void*)s.c_str() << " | " << s << endl; 
    for (int i=0; i<33; ++i) { 
    s += 'a'; 
    cout << (void*)s.c_str() << " | " << s << endl; 
    } 

} 

g++ test.cc && ./a.out輸出是

capacity: 0 
0x7fe405f6afb8 | 
0x7b0c38 | a 
0x7b0c68 | aa 
0x7b0c38 | aaa 
0x7b0c38 | aaaa 
0x7b0c68 | aaaaa 
0x7b0c68 | aaaaaa 
0x7b0c68 | aaaaaaa 
0x7b0c68 | aaaaaaaa 
0x7b0c98 | aaaaaaaaa 
0x7b0c98 | aaaaaaaaaa 
0x7b0c98 | aaaaaaaaaaa 
0x7b0c98 | aaaaaaaaaaaa 
0x7b0c98 | aaaaaaaaaaaaa 
0x7b0c98 | aaaaaaaaaaaaaa 
0x7b0c98 | aaaaaaaaaaaaaaa 
0x7b0c98 | aaaaaaaaaaaaaaaa 
0x7b0cd8 | aaaaaaaaaaaaaaaaa 
0x7b0cd8 | aaaaaaaaaaaaaaaaaa 
0x7b0cd8 | aaaaaaaaaaaaaaaaaaa 
0x7b0cd8 | aaaaaaaaaaaaaaaaaaaa 
0x7b0cd8 | aaaaaaaaaaaaaaaaaaaaa 
0x7b0cd8 | aaaaaaaaaaaaaaaaaaaaaa 
0x7b0cd8 | aaaaaaaaaaaaaaaaaaaaaaa 
0x7b0cd8 | aaaaaaaaaaaaaaaaaaaaaaaa 
0x7b0cd8 | aaaaaaaaaaaaaaaaaaaaaaaaa 
0x7b0cd8 | aaaaaaaaaaaaaaaaaaaaaaaaaa 
0x7b0cd8 | aaaaaaaaaaaaaaaaaaaaaaaaaaa 
0x7b0cd8 | aaaaaaaaaaaaaaaaaaaaaaaaaaaa 
0x7b0cd8 | aaaaaaaaaaaaaaaaaaaaaaaaaaaaa 
0x7b0cd8 | aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa 
0x7b0cd8 | aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa 
0x7b0cd8 | aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa 
0x7b0d28 | aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa 

我猜測,較大的第一指針,即0x7fe405f6afb8是一個堆棧指針,和其他的指向堆。多次運行會產生相同的結果,因爲第一個地址總是很大,而其他地址較小;確切的值通常是不同的。較小的地址總是遵循2分配方案的標準功率,例如, 0x7b0c38列出一次,然後0x7b0c68列出一次,然後0x7b0c38兩次,然後0x7b0c68 4次,然後0x7b0c98 8倍等

閱讀霍華德的答案,使用64位的機器後,我原以爲會看到相同的地址打印爲前22個字符,然後才能看到它的變化。

我錯過了什麼嗎?

另外,有趣的是,如果我-O編譯(任何級別),我在第一種情況下獲得恆定的小指針值0x6021f8,而不是大的價值,這0x6021f8不會改變,無論多少次我運行該程序。

g++ -v輸出:

Using built-in specs. 
COLLECT_GCC=g++ 
COLLECT_LTO_WRAPPER=/foo/bar/gcc-6.2.0/gcc/libexec/gcc/x86_64-redhat-linux/6.2.0/lto-wrapper 
Target: x86_64-redhat-linux 
Configured with: ../gcc-6.2.0/configure --prefix=/foo/bar/gcc-6.2.0/gcc --build=x86_64-redhat-linux --disable-multilib --enable-languages=c,c++,fortran --with-default-libstdcxx-abi=gcc4-compatible --enable-bootstrap --enable-threads=posix --with-long-double-128 --enable-long-long --enable-lto --enable-__cxa_atexit --enable-gnu-unique-object --with-system-zlib --enable-gold 
Thread model: posix 
gcc version 6.2.0 (GCC) 
+1

'--with-default-libstdcxx-abi = gcc4-compatible' –

+0

@ T.C。真? 'gcc4'沒有小字符串優化? – SU3

+0

我以爲我記得小字符串優化必須放回(回)到語言 – xaxxon

回答

13

你的一個標誌是:

--with-default-libstdcxx-abi=gcc4-compatible 

和GCC4不支持小串optimzation。


GCC5開始支持它。 isocpp states:

默認情況下啓用std :: string的新實現,使用小字符串優化而不是寫入時複製引用計數。

它支持我的說法。

此外,Exploring std::string提到:

正如我們看到的,年紀大的libstdC++工具寫入時複製,所以它使 感爲他們不使用的小物件優化。

然後當GCC5進場時他改變了上下文。