C++——内存管理

为了更好的介绍C++的内存管理,我们先来复习一下进程地址空间中各个区段的分布吧!

一、进程地址空间

我们假设从上到下地址由高向低递减,最上面的是所谓的内核区域,内核区域不允许我们程序员进行任何的读写操作。

再往下呢,就是我们十分熟悉的栈区,栈的空间中存储的是我们程序中开辟的局部变量,与函数的形参等等。 

栈上开辟的变量其生命周期是取决于当前的作用域的,定义在main函数内部的变量出了main函数就销毁,而如果内部还有一个花括号括起来的代码段的话,其内部的临时变量的生命周期就是出了这个花括号就销毁。

再往下走,就是内存映射区,这个区域笔者不会细讲,具体的介绍留到linux下介绍!

继续往下是堆区,堆区相信大家也很熟悉了,C中使用如malloc这样动态开辟的空间都是在堆上开辟的,堆中的申请的内存需要程序员自己手动释放,虽然进程退出后OS会回收所有的资源,但是可能会存在着死循环而退出不了的进程,这样会造成严重的内存泄漏。

 再往下的是我们的数据区,

数据区又称作静态区,它负责存放的是我们的全局变量和静态变量,这些变量的特点是生命周期为整个程序。实际上这个区域又分为已初始化全局数据区与为初始化的全局数据区,具体的介绍我们依旧留在下一次。

最后一个区域是代码区,代码区中存放的是我们程序运行的代码,以及我们的只读常量,包括字符串啊这些的。

 二、C++关键字 new与delete

C++在内存管理方面,像C中的malloc,calloc,realloc以及free等函数都是可以使用的,但是为了更好的适应C++引入的类,C++加入了newdelete两个关键字,它们能够更好的处理创建一个类和销毁一个类的工作,后面的介绍读者将会体会到这一点。

我们先来看一下new和delete如何使用吧!

我们在使用delete创建一个数组空间的时候,它与delete的配合要适应,都要加方括号。并且我们开辟数组空间时它并不会为我们初始化, 

这和malloc是一样的,实际上new的底层原理就是使用malloc实现的,只不过它在开辟失败的情况下并不返回NULL,而是选择抛出异常。 

那我们是否可以像C中的数组一样,在new开辟的同时为它初始化某些值呢,这是可以的,

 只要在后面加上花括号,添加上需要初始化的值即可。注意,如果我们只初始化部分的数组空间,在后面默认都是初始化为0。

我们可以发现,在开辟空间的时候,对内置类型的处理实际上和malloc没有本质的区别,只不过是简化了异常处理的过程。那是否引入这两个关键字就没有任何的必要呢?并不是!

笔者刚刚已经提到了,new和delete对于类的处理要好于C,下面将会解释这一点。

我们如果使用C中的malloc去创建一个对象,那么它并不会为这个对象初始化,也就是不会调用它的构造函数。那使用new呢?

class A
{
public:
	A()
	{
		cout << "A(int a)" << endl;
	}
	~A()
	{
		cout << "~A()" << endl;
	}
private:
	int _a;
};
int main()
{
	A* p = new A;
	return 0;
}

在这里笔者在构造函数和析构函数中写下一个打印的语句,每次调用都会打印。main函数中new了一个A对象,下面是执行结果。

显然它调用了构造函数,我们再试着把它delete掉。

 

显然delete也调用了这个对象的析构函数,这说明了在new一个对象的时候会调用其构造函数为它初始化,而delete的时候会调用析构函数! 

这是new和delete十分重要的特点,这也正是malloc和free无法替代的原因,因为通过malloc是无法自动调用构造函数的,而malloc一个对象是无法调用到它的构造函数的,free也无法做到释放掉一个对象中资源,它仅仅只是free掉指向这个对象的指针。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值