3

I run a small test program to verify that our tool benefits from SSO:

// Example program
#include <iostream>
#include <string>

int main()
{
    std::cout << sizeof(std::string) << " " << std::string().capacity() << std::endl;
}

Now I am a little bit puzzled by the result: Why does std::string only have a short capacity of 15 bytes, but a memory size of 32? Since 1 byte is a tag, I'd expect a short string length of 31 bytes in that case. What happens to the remaining 16 bytes?

edit: I have digged up the source code.

      struct _Alloc_hider : allocator_type // TODO check __is_final
      {
#if __cplusplus < 201103L
        _Alloc_hider(pointer __dat, const _Alloc& __a = _Alloc())
        : allocator_type(__a), _M_p(__dat) { }
#else
        _Alloc_hider(pointer __dat, const _Alloc& __a)
        : allocator_type(__a), _M_p(__dat) { }

        _Alloc_hider(pointer __dat, _Alloc&& __a = _Alloc())
        : allocator_type(std::move(__a)), _M_p(__dat) { }
#endif

        pointer _M_p; // The actual data.
      };

      _Alloc_hider      _M_dataplus;
      size_type         _M_string_length;

      enum { _S_local_capacity = 15 / sizeof(_CharT) };

      union
      {
        _CharT           _M_local_buf[_S_local_capacity + 1];
        size_type        _M_allocated_capacity;
      };

As you can see, the members _M_dataplus and _M_string_length are outside of the sso union. Together they take 16 bytes (8 for the pointer and 8 for the size). But why is it designed that way? Why not put _M_allocated_capacity into _Alloc_hider and make that part of the union.

choeger
  • 3,562
  • 20
  • 33
  • 1
    https://stackoverflow.com/a/10319672/5084488 this answer may be useful – Alfie Jul 27 '18 at 12:51
  • Actually that answer only confirms my pov unless we assume that all these additional bytes are used for the size field. – choeger Jul 27 '18 at 13:05
  • 1
    When you read the string, you can just access _M_pointer, you don't need to test if you are in the small string or large string case. Various such compromises led to different strategies in libstdc++ vs libc++. – Marc Glisse Jul 28 '18 at 07:07

0 Answers0