赞
踩
new 关键字创建出来的对象位于什么地方?
new首先获取足够大的内存空间,默认为堆空间,在获取的空间中调用构造函数创建对象。delete 调用析构函数销毁对象,归还对象所占的空间
在 C++ 中能够重载 new/delete 操作符,推荐在类中进行局部重载,默认为静态成员函数,不写 static 也是静态成员函数,不推荐全局重载,重载的意义在于改变对象创建时的内存分配方式
有了 new/delete 重载,就可以改变对象创建时的内存分配方式,不一定在堆中分配内存,可以在静态存储区,栈中创建对象。
在类中使用 static 成员变量定义静态存储区的空间,并定义标志,用于表示每块内存是否被占用,空闲为 0,使用中为 1。new 申请空间时,在静态存储空间中寻找一个空闲空间,返回地址。delete 时,检查内存合法后将标志置为 0,表示内存不使用了。
// 52-1.cpp #include <iostream> #include <string> using namespace std; class Test { static const unsigned int COUNT = 4; // 最多存放的对象数量 static char c_buffer[]; // 对象的存储空间 static char c_map[]; // 每个存储对象位置是否空间,0表示空间可用 int m_value; public: void* operator new (unsigned int size) { void* ret = NULL; for (int i = 0; i < COUNT; i++) // 找一个空位放对象 { if ( !c_map[i] ) { c_map[i] = 1; ret = c_buffer + i * sizeof(Test); cout << "succeed to allocate memory: " << ret << endl; break; } } return ret; } void operator delete(void* p) { if (p != NULL) { char* mem = reinterpret_cast<char*>(p); int index = (mem - c_buffer) / sizeof(Test); // 第几个位置 int flag = (mem - c_buffer) % sizeof(Test); // 查看给出的位置是否正确 if (flag == 0 && 0 <= index && index < COUNT) { c_map[index] = 0; // 标志置0,表示空间可用 cout << "succeed to free memory: " << p << endl; } } } }; char Test::c_buffer[sizeof(Test) * Test::COUNT] = { 0 }; char Test::c_map[Test::COUNT] = { 0 }; int main(int argc, char* argv[]) { cout << "==== Test Single Object ====" << endl; Test* pt = new Test; delete pt; cout << "==== Test Object Array ====" << endl; Test* pa[5] = { 0 }; for (int i = 0; i < 5; i++) { pa[i] = new Test; cout << "pa[" << i << "]" << pa[i] << endl; } for (int i = 0; i < 5; i++) { cout << "delete " << pa[i] << endl; delete pa[i]; } return 0; }
主函数中 Test* pa[5] 申请 5 个对象的空间,实际最多只能申请 4 个,所以最后一个申请不成功。
编译运行:
==== Test Single Object ==== succeed to allocate memory: 00CBC5AC succeed to free memory: 00CBC5AC ==== Test Object Array ==== succeed to allocate memory: 00CBC5AC pa[0]00CBC5AC succeed to allocate memory: 00CBC5B0 pa[1]00CBC5B0 succeed to allocate memory: 00CBC5B4 pa[2]00CBC5B4 succeed to allocate memory: 00CBC5B8 pa[3]00CBC5B8 pa[4]00000000 delete 00CBC5AC succeed to free memory: 00CBC5AC delete 00CBC5B0 succeed to free memory: 00CBC5B0 delete 00CBC5B4 succeed to free memory: 00CBC5B4 delete 00CBC5B8 succeed to free memory: 00CBC5B8 delete 00000000
如何在指定地址上创建 C++ 对象?
// 52-2.cpp #include <iostream> #include <string> using namespace std; class Test { static unsigned int c_count; static char* c_buffer; static char* c_map; int m_value; public: static bool SetMemorySource(char* memory, unsigned int size) { bool ret = false; c_count = size / sizeof(Test); ret = c_count && (c_map = reinterpret_cast<char*>(calloc(c_count, sizeof(char)))); if (ret) { c_buffer = memory; } else { free(c_map); c_map = NULL; c_buffer = NULL; c_count = 0; } return ret; } void* operator new (unsigned int size) { void* ret = NULL; if (c_count > 0) { for (int i = 0; i < c_count; i++) { if (!c_map[i]) { c_map[i] = 1; ret = c_buffer + i * sizeof(Test); cout << "succeed to allocate memory: " << ret << endl; break; } } } else { ret = malloc(size); } return ret; } void operator delete(void* p) { if (p != NULL) { if (c_count > 0) { char* mem = reinterpret_cast<char*>(p); int index = (mem - c_buffer) / sizeof(Test); int flag = (mem - c_buffer) % sizeof(Test); if (flag == 0 && 0 <= index && index < c_count) { c_map[index] = 0; cout << "succeed to free memory: " << p << endl; } } else { free(p); } } } }; unsigned int Test::c_count = 0; char* Test::c_buffer = NULL; char* Test::c_map = NULL; int main(int argc, char* argv[]) { char buffer[12] = { 0 }; Test::SetMemorySource(buffer, sizeof(buffer)); cout << "==== Test Single Object ====" << endl; Test* pt = new Test; delete pt; cout << "==== Test Object Array ====" << endl; Test* pa[5] = { 0 }; for (int i = 0; i < 5; i++) { pa[i] = new Test; cout << "pa[" << i << "]" << pa[i] << endl; } for (int i = 0; i < 5; i++) { cout << "delete " << pa[i] << endl; delete pa[i]; } return 0; }
main 函数中的 buffer[12] 在栈中分配空间,将这个地址指定为 new 申请对象的地址,则 new 在栈中分配空间。
C++ 类中成员函数,static 变量不计算入 sizeof,buffer[12] 大小为 12 个字节,Test 大小为 4 字节,所以最多可以放置三个对象,我们申请了 5 个对象,所以只有前三个对象对申请成功。
编译运行
==== Test Single Object ==== succeed to allocate memory: 00B5FE20 succeed to free memory: 00B5FE20 ==== Test Object Array ==== succeed to allocate memory: 00B5FE20 pa[0]00B5FE20 succeed to allocate memory: 00B5FE24 pa[1]00B5FE24 succeed to allocate memory: 00B5FE28 pa[2]00B5FE28 pa[3]00000000 pa[4]00000000 delete 00B5FE20 succeed to free memory: 00B5FE20 delete 00B5FE24 succeed to free memory: 00B5FE24 delete 00B5FE28 succeed to free memory: 00B5FE28 delete 00000000 delete 00000000
1、new/delete 操作符可以重载,推荐针对具体类重载
2、new 默认在堆上分配空间,重载可以在静态存储区、栈上分配空间
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。