当我在尝试重载new和delete操作符时,我注意到了一些奇怪的事情。
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 thenew
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, andnew
is all about dynamic memory.
发生了什么?
更新
在阅读评论并自行调试示例后,我想总结一下:确实,一旦调用字符串构造函数,它会为其内部实现在堆上分配内存。这可以通过跟踪new
调用来看到:
(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
...
阅读 std::string(也就是 basic_string.tcc)源代码:
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;
...
}
所以,编程很酷。
malloc
/free
和new
/delete
是一对。 - Grijesh Chauhanoperator new
中断点,以查看是谁在调用它?流也会分配内存。 - user405725std::string
的整个意义在于它封装了一个char*
并为您拥有/管理它。因此,当您创建一个std::string
时,它会分配一些内存来存储实际的字符。构造函数甚至可以使用自定义分配器。 - BoBTFishfree
实现了delete
,那么是的,但这与问题无关,所以我省略了它。 - Dan Gittikstd::string *s
吗? - phoxis