26

I have a simple question. I want to know whether std::string allocates memory every time in C++.

In my code, it seems that the constructor will use more memory to construct tst_first_string than for tst_second_string:

 char* first_string = new char[5];
 strcpy(first_string, "test");
 std::string tst_first_string(first_string);
 std::string tst_second_string("test");
Mike
  • 8,055
  • 1
  • 30
  • 44
Oscar
  • 1,071
  • 13
  • 26
  • 6
    ***if std::string alloc everytime in c++*** I believe it is implementation defined and with most implementations the answer is no. – drescherjm Oct 06 '16 at 12:45
  • http://stackoverflow.com/questions/21694302/what-are-the-mechanics-of-short-string-optimization-in-libc – tkausl Oct 06 '16 at 12:48

4 Answers4

22

Both tst_first_string and tst_second_string will be constructed using the constructor to const char*. Since the number of characters before the nul-terminator is the same in both cases, you'd imagine that the construction will be exactly identical. That said the C++ standard is intentionally vague as to what must happen with regards to memory management so you will not know with absolute certainty.

Note also that many std::string implementations exploit a short string optimisation technique for small strings which causes the entire object to be written to memory with automatic storage duration. In your case, dynamic memory may not be used at all.

What we do know for certain is that from C++11 onwards, copy on write semantics for std::string is no longer permitted, so two distinct strings will be created.

GJK
  • 37,023
  • 8
  • 55
  • 74
Bathsheba
  • 231,907
  • 34
  • 361
  • 483
  • 3
    It also depends on the allocator. One can use a stack-based allocator so in that case there is no heap involved no matter what. – vsoftco Oct 06 '16 at 13:06
  • 1
    @vsoftco It's not `std::string` any more if you change the allocator. – T.C. Oct 06 '16 at 21:21
  • Well, one should also never neglect the as-if rule, and the additional explicit mandate for omitting / coalescing some more dynamic allocations. – Deduplicator Mar 24 '18 at 00:02
13

It depends on the implementation and length of the string.

Most major implementations have short string optimization (SSO), where the string is stored in the string object itself.

Kent
  • 996
  • 6
  • 10
2

This is implementation-defined, but as an example, the std::basic_string implementation on Visual C++ 2015 Update 3 will use an internal array if the length of the string is less than 16 bytes. Here's a heavily edited portion of _String_val from <xstring>:

template<class _Val_types>
class _String_val
{
public:
    typedef typename _Val_types::value_type value_type;

    enum
    {   // length of internal buffer, [1, 16]
        _BUF_SIZE = 16 / sizeof (value_type) < 1 ? 1
            : 16 / sizeof (value_type)
    };

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

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

If you look at _Myptr(), you'll notice _Buf is used when the length is less than _BUF_SIZE and _Ptr is used otherwise.

Needless to say, you shouldn't rely on this being true for anything else than this particular implementation of the standard library. It is an internal detail that may change at any time.

isanae
  • 3,253
  • 1
  • 22
  • 47
-4

String literals are read-only. So a likely optimisation is that when a std::string points to a literal it consists merely of a char * plus a flag to say this is what it represents. When you write to it of course it will have to allocate memory.

Ronan Boiteau
  • 9,608
  • 6
  • 34
  • 56
Malcolm McLean
  • 6,258
  • 1
  • 17
  • 18
  • While I believe such an optimization is technically legal (you can't write a valid C++ program which can tell whether it is present or not), I am pretty sure no compiler/library (and both would have to cooperate), implement such an optimization. – Martin Bonner supports Monica Oct 06 '16 at 13:21
  • They would need to co-operate, but not deeply. String literals are in a different area of memory to the stack, heap, or (usually) writeable globals. Not that I've ever implemented an std::string. There might be a problem with throw semantics (is str[0] = 'x' allowed to be no throw?). – Malcolm McLean Oct 06 '16 at 14:16
  • @MalcolmMcLean: Copy-on-write isn't allowed for `std::string`, so you can't just point at a string literal and track if it needs to be copied. – GManNickG Oct 06 '16 at 23:56
  • What is disallowed is std::string one = something; std:;string two = one; two is copy on write. Not lazy holding of string literals. (Especially if the std:;string is never const-dequalified). – Malcolm McLean Oct 07 '16 at 07:03
  • Actually, it is forbidden due to `noexcept` and performance guarantees on various members, same as general COW. – Deduplicator Mar 24 '18 at 00:04