2017-09-06 9 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の出力は、私は大きな最初のポインタは、すなわち0x7fe405f6afb8はスタックポインタであることを推測している、と他のものは、ヒープを指す

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 

です。これを何度も実行すると、最初のアドレスは常に大きく、他のアドレスは小さいという意味で同じ結果が得られます。正確な値は通常異なる。より小さいアドレスは常に、2の割り当てスキームの標準電力に従う。 0x7b0c38は、一度表示されて、その後0x7b0c68が一度表示されて、その後0x7b0c38二回、その後、0x7b0c68 4回、その後、0x7b0c98 8回、など

64ビットマシンを使用して、ハワードの答えを読んだ後、私は印刷された同じアドレスを確認するために期待していました最初の22文字は、それが変わるのを見るだけです。

何か不足していますか?

Iは、(任意のレベルで)-Oでコンパイルした場合また、興味深いことに、私が代わりに大きな値で、最初の場合には一定の小さいポインタ値0x6021f8を取得し、この0x6021f8に関係なく何回変化しません私はプログラムを実行する。 g++ -v

出力:

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

とGCC4はないサポート小さな文字列optimzationを行います。

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

あなたのフラグの一つがあります。


GCC5がサポートを開始しました。 isocpp状態:

のstd ::文字列の新しい実装では、コピー・オン・ライト参照カウントの代わりに小さな文字列の最適化を使用して、デフォルトで有効になっています。私の主張を支持する

また、Exploring std::string言及:にlibstdC++

我々は見ての通り、古い道具がオン・ライト - コピーして、それは彼らが小さなオブジェクトの最適化を利用しないするため 理にかなっています。

そして、彼はGCC5が場に出たときに文脈を変えます。

関連する問題