Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is std::string guaranteed not to give back memory spontaneously?

Is it guaranteed by the standard that std::string will not give back allocated memory spontaneously if reassigned from a string of a smaller size?

In other words:

std::string str = "Some quite long string, which needs a lot of memory";
str = "";
str = "A new quite long but smaller string"; // Guaranteed to not result in a heap allocation?

I ask because i'm depending on this to avoid heap fragmentation.

like image 247
Martin G Avatar asked Sep 25 '18 10:09

Martin G


People also ask

Is std::string dynamically allocated?

Inside every std::string is a dynamically allocated array of char .

Does std::string allocate memory?

While std::string has the size of 24 bytes, it allows strings up to 22 bytes(!!) with no allocation.

Is std::string allocated on the heap?

The string object itself is stored on the stack but it points to memory that is on the heap. Why? The language is defined such that the string object is stored on the stack. string's implementation to construct an object uses memory on the heap.

How are C++ strings stored in memory?

@user1145902: They are stored in memory like in an array, but that memory is not allocated in the stack (or wherever the string object is), but rather in a dynamically allocated buffer.


2 Answers

No guarantee whatsoever.

[string.cons]/36 defines assigning a const char* to an std::string in term of a move-assignment, whose definition is:

[string.cons]/32

basic_string& operator=(basic_string&& str)  noexcept(/*...*/)

Effects: Move assigns as a sequence container, except that iterators, pointers and references may be invalidated.

This shows that the Committee let the implementation choose freely between an invalidating operation and a more conservative one. And to make things even clearer:

[basic.string]/4

References, pointers, and iterators referring to the elements of a basic_­string sequence may be invalidated by the following uses of that basic_­string object:

  • (4.1) as an argument to any standard library function taking a reference to non-const basic_­string as an argument.
  • (4.2) Calling non-const member functions, except operator[], at, data, front, back, begin, rbegin, end, and rend.

I ask because i'm depending on this to avoid heap fragmentation.

std::string takes as template-parameter an allocator. If you're really concerned by a possible heap fragmentation, you could write your own, which with some heuristics could have an allocation strategy suited for your needs.

In practice, most implementations I know of would not reallocate memory in the case of your question. This can be checked by testing and/or checking your implementation doc and eventually source code.

like image 58
YSC Avatar answered Oct 18 '22 20:10

YSC


CPP reference states that assignment to a pointer-to-char

Replaces the contents with those of null-terminated character string pointed to by s as if by *this = basic_string(s), which involves a call to Traits::length(s).

This "as if" actually boils down to an rvalue assignment, so the following scenario is quite possible:

  1. A fresh temporary string is created.
  2. This string steals its contents as via assignment to an rvalue reference.
like image 13
bipll Avatar answered Oct 18 '22 20:10

bipll