C++动态内存管理核心知识点总结
2017-03-12 01:35
148 查看
动态内存管理核心:
首先,我们来重载一下operator new ();进行预处理,给我们打印一些有用的 信息,比如:当前定位的行号,开辟空间的大小(方便我们对于内存泄漏的检查)
效果如图所示:
下来,我们对new/delete 和new[]和delete[]进行仿写,了解一下底层实现
接下来,我们再来看一下为什么一定要匹配使用?
程序执行完,并没有发生错误。
因为对于内置类型和没有显示给出析构函数的类,系统可以直接释放。
那我们显示给出析构函数看一下程序执行结果。从上面的导图饿哦们可以大致了解到,对于非内置类型或无自定义析构函数的类类型来说,析构一段数组空间时,需要知道数组的大小。
此时。程序就会发生崩溃,这就是我们为什么要配套使用new/delete 与new[]/delete[] 的原因了。
new[]的开辟四个字节空间图:
注:该图来自于:http://blog.csdn.net/hazir/article/details/21413833
首先,我们来重载一下operator new ();进行预处理,给我们打印一些有用的 信息,比如:当前定位的行号,开辟空间的大小(方便我们对于内存泄漏的检查)
#include<iostream> using namespace std; class Test { public: Test() { cout << "Test()" << endl; } ~Test() { cout << "Test()" << endl; } private: int _data; }; void* operator new(size_t size, const char*fileName, const char*funcName, int lineNo) { cout << fileName << ":" << funcName << "--" << lineNo << endl; cout << size <<endl; return malloc(size); } #if _DEBUG #define new new(__FILE__,__FUNCDNAME__,__LINE__) #endif //此时需要对operator new 进行重载,系统中没有合适的operator new void FunTest() { Test*p = new Test; } int main() { FunTest(); return 0; }
效果如图所示:
下来,我们对new/delete 和new[]和delete[]进行仿写,了解一下底层实现
#include<iostream> using namespace std; class Test { public: Test() { cout << "Test()" << endl; } ~Test() { cout << "~Test()" << endl; } private: int _data; }; Test* New(size_t size) { Test* p = (Test*)malloc(size); if (NULL == p) { return p; } //执行构造函数 new(p)Test;//定位new 表达式执行构造函数 return p; } //delete ->析构函数-》释放空间 void Delete(Test*p) { //要调用函数,那就要对调用它的指针进行判空处理 if (p) { p->~Test(); free(p); } } //new[]-->malloc //多开辟四个字节来保存数组数量 Test* NewArray(size_t count) { int *p = (int *)malloc(count + 4); //malloc之后就要对返回值进行判空处理 if (p == NULL) { //return p;//直接返回p与声明类型不一致 return NULL; } *p = count; //p = (Test*)(p + 1);->类型不匹配,我们重新定义一个指针 Test* pt = (Test*)(p + 1); for (size_t idx = 0; idx < count; ++idx) { //使用定位new表达式 new(pt + idx)Test; } return pt;//返回起始构造函数的位置 } //delete[] void DeleteArray(Test*p) { //分情况-》空,不空 if (p == NULL) { return; } int count = *((int *)p - 1); //从后往前析构 for (int idx = count - 1; idx >= 0; --idx) { (p + idx)->~Test(); } free((int *)p - 1);//从开辟的起始位置进行释放 } void FunTest1() { Test*p = New(sizeof(Test)); Delete(p); Test*p1 = NewArray(10); DeleteArray(p1); } int main() { FunTest1(); //FunTest(); return 0; }
接下来,我们再来看一下为什么一定要匹配使用?
#include<iostream> using namespace std; class Date { private: int _year; int _month; int _day; }; void FunTest1() { int *p1 = new int[5]; int *p2 = new int[5]; int *p3 = new int(2); int* p4 = new int(3); delete p1; delete[]p2;// delete p3; delete[]p4;//因为int 为内置类型,所以析构时无需知道数组的大小 } void FunTest2() { Date* p1 = new Date(); Date*p2 = new Date(); Date*p3 = new Date[5]; Date*p4 = new Date[5]; delete p1; delete[] p2; delete p3; delete[] p4; } int main() { FunTest1(); FunTest2(); return 0; }
程序执行完,并没有发生错误。
因为对于内置类型和没有显示给出析构函数的类,系统可以直接释放。
那我们显示给出析构函数看一下程序执行结果。从上面的导图饿哦们可以大致了解到,对于非内置类型或无自定义析构函数的类类型来说,析构一段数组空间时,需要知道数组的大小。
#include<iostream> using namespace std; class Date { public: /*Date(int year = 0, int month = 0, int days = 0) :_year(year) , _month(month) , _day(days) { }*/ ~Date() { } private: int _year; int _month; int _day; }; void FunTest1() { int *p1 = new int[5]; int *p2 = new int[5]; int *p3 = new int(2); int* p4 = new int(3); delete p1; delete[]p2;// delete p3; delete[]p4;//因为int 为内置类型,所以析构时无需知道数组的大小 } void FunTest2() { Date* p1 = new Date(); Date*p2 = new Date(); Date*p3 = new Date[5]; Date*p4 = new Date[5]; delete p1; delete[] p2; delete p3; delete[] p4; } int main() { FunTest1(); FunTest2(); return 0; }
此时。程序就会发生崩溃,这就是我们为什么要配套使用new/delete 与new[]/delete[] 的原因了。
new[]的开辟四个字节空间图:
注:该图来自于:http://blog.csdn.net/hazir/article/details/21413833
相关文章推荐
- PHP核心知识点总结
- HBase核心知识点总结
- 知识点总结_(做内容管理系统之后总结1)
- 考研数学核心知识点总结
- 系统集成项目管理工程师教程知识点总结3
- 各类算法技巧核心代码,知识点归纳总结之单调递增子序列
- linux磁盘格式化与管理知识点总结
- Linux系统管理知识点总结
- Oracle 11g 第九章知识点总结——创建和管理表
- 【C】C语言核心知识点总结(Reference Manual)
- 项目管理学习总结(8)——项目管理核心三要素
- 面试题总结之SpringMVC核心知识点
- PMP知识点总结—配置管理
- JavaScript核心知识点总结
- C#酒店管理重要知识点总结
- Oracle知识点总结—常用数据类型与表的管理
- Android核心基础(手机卫士的一个知识点总结)
- 项目管理小小知识点总结
- Java核心技术 卷1 知识点总结
- 【数据库】数据查询和管理知识点总结