String Allocation In C++
c++, memory, string
Solution
When you write
std::string s = "Hello world";
you are calling the constructor `string (const char* s);`, the specification of this constructor is `Copies the null-terminated character sequence (C-string) pointed by s.` So the constructor allocates memory to store the copy.
Problem
I was playing with the new and delete operators overloading when I noticed something strange. I have: ``` void* operator new(size_t size) { std::cout << "Allocating memory..." << std::endl; void* p = malloc(size); if (NULL == p) { throw std::bad_alloc(); } return p; } ``` When I do: ``` int main() { int* x = new int(1); std::cout << *x << std::endl; delete x; return EXIT_SUCCESS; } ``` Everything works as expected and I get: ``` Allocating memory... 1 ``` But when I do: ``` int main() { std::string* s = new std::string("Hello world"); std::cout << *s << std::endl; delete s; return EXIT_SUCCESS; } ``` I get: ``` Allocating memory... Allocating memory... Hello world ``` In fact, when I do: ``` int main() { std::string s = "Hello world"; return EXIT_SUCCESS; } ``` I still get `Allocating memory...`! Finally, I do: ``` int main() { std::string s = "Hello world"; std::cout << &s << std::endl; while (true); } ``` To get something like: ``` $ ./test & [1] 8979 Allocating memory... 0xbfc39a68 $ cat /proc/8979/maps | grep stack bfc27000-bfc3c000 ... [stack] ``` So now I'm sure the `s` variable is allocated on the stack... but then, what's calling the `new` operator? My best guess would be it has something to do with the memory allocation for the actual literal, `"Hello world"`... but it's supposed to be static memory, and `new` is all about dynamic memory. What's going on? Update After reading the comments and debugging the example myself I wanted to conclude that indeed, once the string constructor is called, it allocates memory on the heap for its internal implementation. This can be seen by tracing the `new` call: ``` (gdb) b 13 // that's the std::cout << "Allocating memory..." << std::endl; line (gdb) r ... Breakpoing 1, operator new (size=16) at test.cpp:13 ... (gdb) backtrace #0 operator new (size=16) at main.cpp:13 #1 std::string::_Rep::_S_create(unsigned int, unsigned int, std::allocator<char> const&) () from /usr/lib/libstdc++.so.6 ... ``` And reading the std::string (well, basic_string.tcc) source code: ``` template<typename _CharT, typename _Traits, typename _Alloc> typename basic_string<_CharT, _Traits, _Alloc>::_Rep* basic_string<_CharT, _Traits, _Alloc>::_Rep:: _S_create(size_type __capacity, size_type __old_capacity, const _Alloc& __alloc) { ... void* __place = _Raw_bytes_alloc(__alloc).allocate(__size); _Rep *__p = new (__place) _Rep; // Bingo! __p->_M_capacity = __capacity; ... } ``` So yeah. Programming's cool.