Theory:
Legacy c-strings
Consider the following snippet:
int x[10];
void method() {
int y[10];
}
The first declaration, int x[10], uses static storage duration, defined by cppreference as: "The storage for the object is allocated when the program begins and deallocated when the program ends. Only one instance of the object exists. All objects declared at namespace scope (including global namespace) have this storage duration, plus those declared with static or extern."
In this case, the allocation happens when the program begins and freed when it ends. From cppreference.com:
static storage duration. The storage for the object is allocated when the program begins and deallocated when the program ends.
Informally, it is implementation-defined. But, since these strings never change they are stored in read-only memory segments (.BSS/.DATA) of the executable and are only referenced during run-time.
The second one, int y[10], uses automatic storage duration, defined by cppreference as: "The object is allocated at the beginning of the enclosing code block and deallocated at the end. All local objects have this storage duration, except those declared static, extern or thread_local."
In this case, there is a very simple allocation, a simple as moving the stack pointer in most cases.
std::string
A std::string
on the other hand is a run-time creature, and it has to allocate some run-time memory:
- For smaller strings, std::string has an inner buffer with a constant size and is capable of storing small strings (think of it as a
char buffer[N]
member)
- For larger strings, it performs dynamic allocations.
Practice
You could use reserve()
. This method makes sure that the underlying buffer can hold at least N charT's.
Option 1: First reserve, then append
std::string str;
str.reserve(6);
str.append("Hi");
Option 2: First construct, then reserve
std::string str("Hi");
str.reserve(6);