#stl VS 2005의 std::string 구현(딩컴웨어 STL)

1 minute read

Effective STL 항목 15에서 string이 여러 가지 방식으로 구현되어 있다는 걸 상기시키고 있다. 구현 방법까지 표준 문서에 정의하지 않았기 때문에 당연한 결과이기도 하다. VS 2005에 포함된 딩컴웨어 STL은 어떻게 구현되었나 궁금해서 찾아봤다.

책에서는 4가지 타입의 구현 방법을 설명해놨는데, 딩컴웨어의 string 구현을 보고 D 타입을 적었던 거 같다. 짧은 문자는 동적 할당을 하지 않고 내부 버퍼를 사용하는 단문자열 최적화(small string optimization) 구현이 되어 있었다.

단문자열 최적화를 위한 내부 버퍼

union _Bxty
{    // storage for small buffer or pointer to larger one
    _Elem _Buf[_BUF_SIZE];
    _Elem *_Ptr;
} _Bx;

이렇게 버퍼가 정의되어 있다. _BUF_SIZE를 계산할 때 16을 sizeof(_Elem)로 나누는데, 이 때문에 _Buf에 16바이트가 할당된다. 여기서는 문자열의 끝을 널 문자(null character)로 표시하는 C 스타일 문자열을 사용한다.

_Elem *__CLR_OR_THIS_CALL _Myptr()
{    // determine current pointer to buffer for mutable string
    return (_BUF_SIZE <= _Myres ? _Bx._Ptr : _Bx._Buf);
}

버퍼에 대한 접근은 이 함수를 통해서 하는데, size가 아니라 capacity(_Myres)를 _BUF_SIZE와 비교한다.

sizeof(std::string)

string a("123456789abcdefghijklmn");
string b;
cout << "sizeof(string:123456789abcdefghijklmn) : " << sizeof(a) << endl;
cout << "sizeof(string:                       ) : " << sizeof(b) << endl;

nil

저장된 문자열의 길이에 상관없이 string 객체는 항상 같은 사이즈를 가진다. 내부 버퍼 사이즈를 넘어선 문자열을 저장할 때 버퍼 사이즈를 늘이지 않고 동적으로 할당한 버퍼를 가리키는 포인터를 가지기 때문.

capacity, size를 저장하는 변수가 각각 4바이트, 내부 버퍼 16바이트, 디버깅 헬프 4바이트, 할당자 4바이트를 사용해서 32 바이트가 나온다. 릴리즈 빌드에서는 디버깅을 도와주는 것들이 빠지기 때문에 28바이트가 나온다.