First read about how std::string
works. Check these links: An introduction to std::string and std::string
On my compiler (GCC v11.2) the size of small string buffer is 16. So a std::string
object has a size of 8+8+16 == 32 bytes; A pointer to the buffer, an integer to store the capacity, and the SS buffer itself.
With all this in mind, now if you declare a std::string
like this:
std::string str;
then the str
will have a 16-byte buffer on the stack. But only the 0th index will be initialized to '\0' and the remaining 15 bytes might contain garbage. So if you print it out, it will only print the '\0' which will not be shown on the screen. So you'll see nothing.
Now take a look at this example:
#include <iostream>
int main( )
{
std::string a; // default constructed
std::string b; // default constructed
std::string c( 10, '\0' ); // but c is now initialized with 10 null terminator
// characters and safe to be used with operator[]
std::cout << "address of a: " << &a << '\n'
<< "address of b: " << &b << '\n'
<< "address of c: " << &c << '\n';
std::cout << '\n';
std::cout << std::showbase << std::hex
<< "address of a's underlying array: " << reinterpret_cast<uint64_t>( a.data( ) ) << '\n'
<< "address of b's underlying array: " << reinterpret_cast<uint64_t>( b.data( ) ) << '\n'
<< "address of c's underlying array: " << reinterpret_cast<uint64_t>( c.data( ) ) << '\n';
std::cout << std::noshowbase << std::dec << '\n';
std::cout << "size of a's underlying array: " << a.size( ) << '\n'
<< "size of b's underlying array: " << b.size( ) << '\n'
<< "size of c's underlying array: " << c.size( ) << '\n';
std::cout << '\n';
std::cout << "a's first element's ASCII: " << static_cast<int>( a[0] ) << '\n'
<< "b's first element's ASCII: " << static_cast<int>( b[0] ) << '\n'
<< "c's first element's ASCII: " << static_cast<int>( c[0] ) << '\n';
std::cout << '\n';
std::cout << "a's second element's ASCII: " << static_cast<int>( a[1] ) << '\n'
<< "b's second element's ASCII: " << static_cast<int>( b[1] ) << '\n'
<< "c's second element's ASCII: " << static_cast<int>( c[1] ) << '\n';
std::cout << '\n';
a = "World";
b = "Apple";
c[1] = a[1]; // here you modify a location that now contains actual data
a[1] = b[1]; // ok
b[1] = c[1]; // here you no longer read from a location that is uninitialized
// and thus does not contain garbage
std::cout << a << '\n';
std::cout << b << '\n';
std::cout << c << '\n';
}
The possible output:
address of a: 0x5738bff710 //
address of b: 0x5738bff730 // these are the addresses of stack locations
address of c: 0x5738bff750 //
address of a's underlying array: 0x5738bff720 // these are also the addresses of stack
address of b's underlying array: 0x5738bff740 // locations since your strings are
address of c's underlying array: 0x5738bff760 // small and not heap allocated
size of a's underlying array: 0 // a has a 16 byte buffer but uninitialized
size of b's underlying array: 0 // b has a 16 byte buffer but uninitialized
size of c's underlying array: 10 // c has a 16 byte buffer but 10 chars are initialized
a's first element's ASCII: 0 // null terminator
b's first element's ASCII: 0 // null terminator
c's first element's ASCII: 0 // null terminator
a's second element's ASCII: 0 // null terminator but can be garbage too
b's second element's ASCII: 26 // here it's garbage
c's second element's ASCII: 0 // can only be null terminator since c's buffer
// has been initialized with 10 null terminators
Wprld
Aople
o // now you can see the letter `o` from the c variable being printed
When a std::string
object is declared, a block of memory is allocated to it. If the number of char
s that it stores is below a certain implementation defined limit (e.g. 16 or 24 byes), the block will be allocated on the stack. This trick is called as SSO. But if it's larger than that limit then a dynmaic memory allocation will need to happen to store the char
s on the heap.
Now in your case, since you don't initialize c
it means that it has an empty buffer on the stack. So your code can cause some undefined behavior if you use operator[] for indices greater than 0.