c++动态内存开辟
来源:互联网 发布:数据采集 久其格格 编辑:程序博客网 时间:2024/05/29 07:33
首先,来谈一谈内存管理:
来看一道很有意思的题目:
int i = 1;static int j = 1;//i和j都在数据段(静态区),但链接属性不一样,static在外部文件不可见void test1(){ static int k = 1;//j和k都是static,生命周期一样,但作用域不一样,static不改变变量的作用域 int n = 1;//k和n的生命周期不一样,作用域一样}void test(){ //sizeof() strlen() int a[10] = { 1, 2, 3, 4 }; //数组 12 char a2[] = "abcd"; //数组 5 4 char* a3 = "abcd"; //指针 4 4 //a2[0]在栈,a3[0]在代码段(常量区)}
这是我的分析:
在c语言里,如何理解:
void test(){ int* p1 = (int*)malloc(sizeof(int)*4);}
接下来进入正题,c++用 new/delete 来实现动态内存开辟:
void test1(){ int* p1 = new int; int* p2 = new int(3); int* p3 = new int[3]; delete p1; delete p2; delete[] p3;}
注意,malloc/free new/delete new[]/delete[]一定要cp使用,一定要cp。
为什么要cp?malloc/free和new/delete之间有什么关系和差异呢?
首先,malloc/free是库函数,new/delete是自定义类型,而且和构造函数,析构函数有关,那么我写一个简单的SeqList类来说明问题:
class Seqlist{public: Seqlist(size_t n = 1) :_a(new int[n]) { cout << "构造函数" << endl; } ~Seqlist() { cout << "析构函数" << endl; delete[] _a; }private: int* _a;};
可以看出,new是在创建对象的同时还会调用构造函数,delete清理对象的同时还会调用析构函数。
SeqList* p2 = (SeqList*)malloc(sizeof(SeqList) * 3); free(p2);
然后malloc和free不会调用,只是开辟空间和清理。
所以说,不匹配使用时极容易出错。比如:
SeqList* p1 = new SeqList[3];//调用三次构造函数 free(p1);
这里new调用了三次构造函数,但是没有和delete匹配使用,导致没有释放_a指针,存在内存泄漏。
具体分析如下:
所以p1应该这样释放:
delete[] p1;//调用三次析构函数
内存泄漏存在很大危害,这个我在研究。
当我调试的时候,new语句跳转时会出现一个函数:operator new,
同样的,delete语句也会跳转到operator delete
这里先声明一点,operator new与operator delete不是重载,它们是函数。
其实operator new是malloc的一层封装.
我们知道,malloc失败了返回0,而operator new失败了会抛异常,它们处理错误方式不同。
//库函数void *__CRTDECL operator new(size_t size) _THROW1(_STD bad_alloc) { // try to allocate size bytes void *p; while ((p = malloc(size)) == 0) if (_callnewh(size) == 0) { // report no memory static const std::bad_alloc nomem; _RAISE(nomem); } return (p); }
可以清楚地看到封装关系。
总结:
new:1.调用operator new,operator new再调malloc分配空间。
2.调用构造函数。
delete:1.调用operator delete,operator delete再调free释放空间.
2.调用析构函数。
这里有一个问题,上面的一个代码:
SeqList* p1 = new SeqList[3];//调用三次构造函数delete[] p1;//调用三次析构函数
既然[]里没有指定大小,那么怎么知道析构三次呢?
上文谈到:
new:1.调用operator new,operator new再调malloc分配空间。
2.调用析构函数。
调试说明问题:
这是malloc,它的res指针返回给operator new的指针p。
这里可以清楚的看到指针的地址。
但是当地址传给p1时却不是4aa0.
而是向后给了4字节,通过查阅资料,原来这四个字节才是问题的关键所在。
所以说,malloc/free new/delete new[]/delete[]一定要cp使用,一定要cp。
如果:new[] ->free,free释放返回的地址,肯定崩溃。
如果:new[] -> delete:会崩溃,因为delete会认为是new出来的,不会往前移四字节,,只析构一次,一定崩溃。
如果:new -> delete[]:会崩溃,因为delete[]会认为是new[]出来的,往前移动必然崩溃。
- c语言动态开辟内存
- c语言动态开辟内存
- 动态内存开辟(c)
- c语言动态内存开辟
- c语言实现通讯录(动态内存开辟)
- 【C】简单动态内存开辟(1)!!
- (C语言)动态内存开辟
- 【C】动态内存开辟(2)——动态内存开辟实例!!!
- 动态开辟内存总结
- 动态内存开辟
- 动态内存开辟
- 动态内存开辟
- c++动态内存开辟
- 动态内存开辟
- C语言内存管理和动态内存开辟
- C开辟内存
- c/c++多维数组的动态内存开辟与释放
- 【C语言】通讯录:动态开辟内存版和文件版本
- pc 链接ubunut
- 连接管理器 AcquireConnection 方法调用失败
- XRecyclerView
- Find Minimum in Rotated Sorted Array II
- 被解救的Django【2】
- c++动态内存开辟
- HTML输入类型(input元素)
- LruCache详解
- WEBRTC FEC/NACK 前向纠错码
- 10月31日(第2天_列表的使用)
- 图形用户界面
- 使用xpath来爬一点点小东西
- 唯快不破:redis源码剖析02-adlist双向链表结构
- 将数据库1的表及表内容复制到数据库2