c++内存管理:
创始人
2024-01-16 20:12:34
0

目录

new和delete

使用方法:

注意事项:

new申请不需要检查返回值

operator new和operator delete函数的讲解


c语言申请内存有哪些方法:

答:malloc  calloc realloc三种

#include
void test()
{int*p1 = (int*)malloc(sizeof(int));free(p1);int*p2 = (int*)calloc(4, sizeof(int));int *p3 = (int*)realloc(p2, sizeof(int)* 10);free(p3);
}

其中,malloc就是普通的动态内存申请

calloc相当于malloc加上memset把申请的空间全部初始化为0

realloc相当于内存扩容,分为异地扩容和原地扩容,当扩容的次数少,空间小时,会执行原地扩容,当扩容的次数多,空间大时,会执行异地扩容。

原地扩容和异地扩容的区别?

答:如上图代码所示,p2和p3指针指向同一块空间,而异地扩容则不然,异地扩容会先找一块新的空间,然后把原空间的内容拷贝到新空间位置,然后释放掉原空间,所以返回的就是p3.

new和delete

使用方法:

c++是通过什么申请内存的呢?

答:c++是通过两个关键字(操作符)来申请和释放空间的。

new和delete

int main()
{int *p1 = new int;delete p1;return 0;
}

相当于这里申请一个字节的空间,返回指向该空间的指针p1,然后delete表示释放空间。

注意:这里申请空间并不会对空间上的内容完成初始化:

例如:

 我们申请的空间并没有进行初始化。

我们如何申请空间的同时并初始化呢?

答:我们可以这样操作

例如:

int main()
{int *p1 = new int(0);delete p1;return 0;
}

 我们在后面加上0表示申请空间并把空间初始化为0.

我们如何申请多个空间呢?

答:

int main()
{int *p1 = new int[10];delete[] p1;return 0;
}

这里表示我们要申请十个整型空间,注意:我们在delete释放时,要和我们申请的空间进行一一对应。

 假如我们要对申请的多个空间进行初始化呢?

答:我们可以这样写:

int main()
{int *p1 = new int[10]{1, 2, 3, 4};delete[] p1;return 0;
}

这里表示我们对申请的十个空间中的前4个进行初始化:

 我们发现,对于内置类型,这里的new和delete和c语言的动态内存申请函数本质上没什么区别,那为什么++要定义这两个关键字呢?

答:对于内置类型,c语言和c++的动态内存申请本质是一样的,但是对于自定义类型,结果就不同了

例如:

我们写一个简单的类:

class A
{A(int a = 0):_a(a){cout << "A():" << this << endl;}~A(){cout << "~A():" << this << endl;}
private:int _a;
};

这个类中有两个成员函数,分别是构造函数和析构函数,函数的目的是当调用构造和析构函数,打印对应的提示并打印出this指针。

我们进行实验:

int main()
{/*int *p1 = new int[10]{1, 2, 3, 4};delete[] p1;return 0;*/A* p1 = new A;}

我们动态内存申请一个类的空间,返回指向该空间的指针p1

我们进行编译:

 这里表示我们的动态内存申请new调用了构造函数。

但是我们的malloc是不会调用构造函数的:

int main()
{/*int *p1 = new int[10]{1, 2, 3, 4};delete[] p1;return 0;*//*A* p1 = new A;*/A*p1 = (A*)malloc(sizeof(A));
}

我们进行编译:

 所以new相较于malloc对于自定义类型来说,new会调用自定义类型的构造函数,而malloc不会。

new会调用自定义类型的构造函数,那么delete是不是也会调用析构函数?

答:会:

int main()
{/*int *p1 = new int[10]{1, 2, 3, 4};delete[] p1;return 0;*/A* p1 = new A;/*A*p1 = (A*)malloc(sizeof(A));*/delete p1;
}

我们进行调用:

 所以delete也会调用自定义类型的析构函数。

我们举一个之前写的链表的例子:

struct ListNode
{ListNode(int val = 0):_next(nullptr), _val(val){}ListNode* _next;int _val;
};

我们现在可以这样写链表:

struct和class都是类关键字,struct当我们不处理时,类中的成员的默认用public修饰。

我们可以在类中写构造函数,相当于我们之前的创建新节点

int main()
{ListNode*n1 = new ListNode(1);ListNode*n2 = new ListNode(2);ListNode*n3 = new ListNode(3);ListNode*n4 = new ListNode(4);n1->_next = n2;
}

这样写链表就会方便很多。

注意事项:

注意:

new和delete一定要匹配,否则会产生意想不到的问题,我们就只举一个例子:

例如:

nt main()
{A*p1 = new A[10];delete p1;
}

我们写出这样的代码进行运行就会报错:

为什么会这样呢?

我们先写一个正常的进行分析:

 

int main()
{A*p1 = new A[10];delete[] p1;
}

我们的A的成员只有一个整型,所以A占四个字节的空间,十个A就占40个字节的空间。

 我们先进行编译:

 我们进行申请时或进行释放时,都会调用多次调用构造函数或析构函数。

我们在创建时,知道我们需要创建十个A类所占的空间

但是我们在析构的时候,并不清楚我们需要析构多少次,这时候,我们需要额外申请一个整型的空间:

 接下来,我们把p1往前置:

 这时候,我们就知道我们需要析构多少次,并且从这里可以把我们申请的空间全部释放。

我们返回来看之前报错的情况:

 

int main()
{A*p1 = new A[10];delete p1;
}

为什么会报错呢?

答: 因为我们释放没有写[],所以我们构造了十次,但是我们不清楚析构了多少次,所以就会报错。

上面的这些都是关于编译器vs2013的一些情况,举这些例子只是为了说明一定要把申请的空间和delete释放的空间进行对应

new申请不需要检查返回值

我们知道malloc申请大的空间或者连续申请小的空间就会报错:

int main()
{while (1){int *p1 = (int*)malloc(1024 * 1024);if (p1){cout << p1 << endl;}else{cout << "申请失败" << endl;break;}}
}

并且我们知道,当malloc申请失败的时候,会返回空指针,所以我们可以写出以上代码来进行实验:

 

 申请多次的时候,报错

接下来,我们对new进行实验:

int main()
{while (1){int *p1 = new int[1024 * 1024];if (p1){cout << p1 << endl;}else{cout << "申请失败" << endl;break;}}
}

 运行很快就停止了,但是并没有打印出申请失败,说明我们new失败的返回值并不是0,或者说,new失败没有返回值。

new失败的话,就会抛异常,所以我们不需要对返回值进行检查,对于抛异常的问题,我们之后再进行详解。

operator new和operator delete函数的讲解

上述的两个函数是new和delete的底层实现:

 new的底层实现就是通过new调用operator new函数,operator函数中有malloc,调用完毕之后调用构造函数。

注意:operator new函数并不是new的重载。

operator new相当于是一个新的全局函数。

我们看一下operator函数的定义:

 我们可以发现,operator new函数就是malloc函数的封装,无非就是加上了当申请失败时,不反回,而是抛异常。

我们观察一下operator delete函数。

 相当于我们operator的主体部分也是调用了free函数。

我们是否可以使用operator new来申请空间呢?

答:可以:

例如:

int main()
{while (1){char*p1 = (char*)operator new(1024 * 1024 * 1024);cout << (void*)p1 << endl;}
}

operator new的使用方法和malloc相似。

不同点在于:operator new申请失败的话不需要报错,因为会抛异常。

相关内容

热门资讯

新学期新起点国旗下讲话稿 新学期新起点国旗下讲话稿范文(精选3篇)  在学习、工作生活中,我们需要用到讲话稿的情形越来越多,讲...
塑造阳光心态演讲稿 塑造阳光心态演讲稿  态度决定一切,心态影响你的生活和能力,心态改变你的命运。下面是公文站小编给大家...
小学三年级上册语文《给予树》... 人教版小学三年级上册语文《给予树》说课稿  作为一位不辞辛劳的人民教师,常常要写一份优秀的说课稿,说...
一年级语文老师家长会的发言稿 一年级语文老师家长会的发言稿  召开家长会是进行家校合作的一种有效途径。你知道家长会上怎么发言比较好...
小学数学六年级《圆的面积》说... 小学数学六年级《圆的面积》说课稿  说内容:  我备课的内容是小学数学六年级上册第四单元第三节《圆的...
《退位减法》说课稿 《退位减法》说课稿(精选3篇)  作为一位杰出的教职工,编写说课稿是必不可少的,借助说课稿可以有效提...
师说说课稿 导语:师者,所以传道授业解惑也。这是《师说》中的名句,下面是《师说》的说课稿,欢迎参考阅读,希望对大...
大班获奖语言说课稿 大班获奖语言说课稿  “说课”是教学改革中涌现出来的新生事物,是进行教学研究、教学交流和教学探讨的一...
新入职员工表态发言稿 新入职员工表态发言稿(精选6篇)  在发展不断提速的社会中,越来越多地方需要用到发言稿,发言稿在写作...
运动会垒球通讯稿 运动会垒球通讯稿(精选22篇)  大家最不陌生的就是通讯稿了吧,通讯稿的使用频率呈上升趋势,无论是在...
大学生学代会竞选稿 大学生学代会竞选稿  竞选稿是竞选者通往竞选大门的“敲门砖”,一份优秀的竞选稿往往会使竞选者达到事半...
竞选团支书竞选稿 竞选团支书竞选稿7篇  在日新月异的现代社会中,我们都不可避免地要接触到竞选稿,竞选稿可以帮助竞选者...
小学足球说课稿 小学足球说课稿范文(精选3篇)  在教学工作者开展教学活动前,很有必要精心设计一份说课稿,借助说课稿...
卖火柴的小女孩的小学评课稿 卖火柴的小女孩的小学评课稿  篇一:《卖火柴的小女孩》评课稿  一、课堂导入新颖。  常言道:“良好...
《石头书》第一课时说课材料 《石头书》第一课时说课材料  一、说教材  本文是一篇科学小品,通过川川和磊磊两个孩子与勘探队员的交...
军训学生代表发言稿 军训学生代表发言稿(通用15篇)  在不断进步的时代,很多地方都会使用到发言稿,发言稿是在一定的场合...
家长会学生代表的优秀发言稿 家长会学生代表的优秀发言稿(精选10篇)  在当今社会生活中,能够利用到发言稿的场合越来越多,发言稿...
五月份国旗下讲话稿 五月份国旗下讲话稿范文(精选3篇)  在快速变化和不断变革的今天,各种讲话稿频频出现,绝大多数的讲话...
交流会活动通讯稿 交流会活动通讯稿  交流会活动通讯稿分享给大家,交流会活动目的是为营造健康积极的文化氛围,提升团队整...
交通安全主题广播稿 交通安全主题广播稿范文(通用8篇)  有在广播站锻炼的同学们都知道,大家广播前都会提前做好广播稿,漂...