写在开头
在最近学习编程时,总是会思考一些细枝末节的问题,这些问题总是会扰乱我的心绪,可能是由于之前没有认真的探究,或者是曾经探究过,但是已经忘掉了,今天一直在脑海里思考的问题是,为什么有的时候需要用new来创建一个对象或数组或结构体呢?当然,不同的老师可能针对这个问题已经提过不止一次了,但是亲身实践才发现,这些细节也足够让人纠结,所以今天就把学到的内容进行一个总结,以备不时之需。
-
堆与栈的概念
同意堆与栈的区别中对不同场景下的堆栈定义区别:
(1)程序内存布局场景下,堆与栈表示的是两种内存管理方式;
(2)数据结构场景下,堆与栈表示两种常用的数据结构。
-
堆与栈的定义
在编程初期,我们一直都在与栈打交道,从计算导论与程序设计这门课开始,就已经开始接触栈这一概念了,那么栈最基础的知识就不再多提了,需要强调的是栈在物理上的地址空间是连续的,而且后申请的变量具有更小的地址值,而且栈中的数据生命周期与函数相同,函数调用结束了,栈也就随之删除。
但是堆有与栈不相同的内涵,在堆上的数据地址与申请的顺序没有严格的匹配关系,是随机申请的空间,只要不主动释放堆的数据,就会一直存在,所以如果大量申请堆中数据并且没有释放,就会出现内存泄漏的问题。但是释放堆的内存也要注意,应该对所要释放的指针进行判空操作,值得注意的是,老师课上曾强调过在delete指针前,要判断指针是否为空,但是查阅资料后发现好像并不需要这么做,因为g++中会自动判断要释放的指针是否为空,总结来说就是,可以判断,但没必要。但是为了避免释放的指针成为野指针,要把指针赋为NULL。 -
堆与栈的区别
其实说了不少,堆与栈的区别在上面就已经体现出来了。总结来说就是,在需要开辟大量内存空间或者希望控制数据的生存周期时,就应该通过堆,这也是在接下来的数据结构联系中需要注意的细节。
下面是以前曾经用过的动态申请二维数组的方法作为范例:
//动态申请一个m行n列的整形数组
int **p = new int *[m];
for(int i = 0;i < m; ++i)
p[i] = new int[n];
//内存释放
for(i = 0;i < m; ++i)
delete[] p[i];
delete[] p;
事实上,使用C++的STL中vector可以更加方便的完成二维数组的动态申请:
//注意int后面的> >之间要有空格,否则会认为是重载的">>"
vector <vector<int> > p(m,vector<int>(n));
网友评论