当我发现一些奇怪的东西时,我正在玩新的和删除操作符重载.
我有:
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;
}
Run Code Online (Sandbox Code Playgroud)当我做:
int main()
{
int* x = new int(1);
std::cout << *x << std::endl;
delete x;
return EXIT_SUCCESS;
}
Run Code Online (Sandbox Code Playgroud)
一切都按预期工作,我得到:
Allocating memory...
1
Run Code Online (Sandbox Code Playgroud)但当我这样做时:
int main()
{
std::string* s = new std::string("Hello world");
std::cout << *s << std::endl;
delete s;
return EXIT_SUCCESS;
}
Run Code Online (Sandbox Code Playgroud)
我明白了:
Allocating memory...
Allocating memory...
Hello world
Run Code Online (Sandbox Code Playgroud)事实上,当我这样做时:
int main()
{
std::string s = "Hello world";
return EXIT_SUCCESS;
}
Run Code Online (Sandbox Code Playgroud)
我还是得到了Allocating memory...
!
最后,我这样做:
int main()
{
std::string s = "Hello world";
std::cout << &s << std::endl;
while (true);
}
Run Code Online (Sandbox Code Playgroud)
得到类似的东西:
$ ./test &
[1] 8979
Allocating memory...
0xbfc39a68
$ cat /proc/8979/maps | grep stack
bfc27000-bfc3c000 ... [stack]
Run Code Online (Sandbox Code Playgroud)
所以现在我确定s
变量是在堆栈上分配的...但那么,什么叫做new
运营商?我最好的猜测是它与实际文字的内存分配有关,"Hello world"
但它应该是静态内存,而且new
都是关于动态内存的.
这是怎么回事?
在阅读了注释并自己调试示例后,我想得出结论,一旦调用了字符串构造函数,它就会在堆上为内部实现分配内存.通过跟踪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
...
Run Code Online (Sandbox Code Playgroud)
并阅读std :: string(well,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;
...
}
Run Code Online (Sandbox Code Playgroud)
是的.编程很酷.
当你写作
std::string s = "Hello world";
Run Code Online (Sandbox Code Playgroud)
你正在调用构造函数string (const char* s);
,这个构造函数的规范是Copies the null-terminated character sequence (C-string) pointed by s.
如此构造函数分配内存来存储副本.
归档时间: |
|
查看次数: |
2225 次 |
最近记录: |