2017-09-06 2 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

, 하워드의 답변을 읽는 64 비트 기계를 사용한 후 다음 두 번 다음, 다음 0x7b0c68 번 목록에 한 번 다음 0x7b0c68 4 회, 0x7b0c98 8 배, 등을 0x7b0c38을 나열, 나는 같은 주소가 인쇄보기 위해 기다리고 있었다 처음 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 상태 :

표준 : : 문자열의 새로운 구현은 복사 (copy-on-write) 참조 횟수 대신 작은 문자열의 최적화를 사용하여, 기본적으로 활성화되어 있습니다.

내 주장을 뒷받침합니다.

또한, Exploring std::string 언급 : 된 libstdC++

우리가 볼 때, 나이가 구현에 쓰기 - 복사하고, 그래서 그들에게 작은 물체 최적화를 사용하지 할 의미가 있습니다.

그리고 GCC5가 등장 할 때 상황이 바뀝니다.