C++内存分布
一个应用程序通常会占用以下空间,也就是内存四区:
堆区,栈区,数据区,代码区
栈区主要存储一些临时变量,临时变量包括了局部变量、返回值、参数、返回地址等,当这些变量超出了当前作用域时将会自动弹出。该栈的最大存储是有大小的,大致是8192kb,超过该大小将会造成栈溢出。
堆区指的是一个比较大的内存空间,主要用于对动态内存的分配;在程序开发中一般是开发人员进行分配与释放,若在程序结束时都未释放,系统将会自动进行回收。
数据区包含静态存储区和常量区:
静态存储区指的是主要存放全局变量、静态变量的区域,编译器编译时分配内存。将变量定义的类型前加static,则该变量存储在静态存储区
static:
1)只初始化一次
2)只有程序退出才释放
常量区,存放常量,只读状态,不可修改,程序结束后由系统释放
代码区,所有代码编译后的cpu指令会存储在这里
1 |
|
结果:
变量a的地址是:6487628
变量b的地址是:6487624
变量c的地址是:6487623
静态变量d的地址是:4223028
全局变量e的地址是:4223024
可以看出,a,b,c都在栈区,三个变量同属于一个栈内,所以它们地址的索引是连续性的。栈区的地址向下增长,因为栈是先进后出,栈底又是最大地址
d和e说明了全局变量与静态变量都应该存储在静态区
栈区、数据区都是使用栈结构对数据进行存储。
new/delete和malloc/free的区别:
C++ 中使用 new 和 delete 从堆中分配和释放内存,new 和 delete 是C++语言中的两个运算符,malloc/free是C语言标准库中的两个函数
new/delete 比 malloc/free ,都是用来申请动态内存的
new/delete 比 malloc/free 多做了一些事情,new 相对于 malloc 会额外的做一些初始化工作,比如调用构造函数。delete 相对于 free 多做一些清理工作,比如调用析构函数。malloc/free无法调用构造和析构的原因是,他是库函数不是运算符,不在编译器控制权限之内
malloc得到的指针无类型,new出来的指针是带有类型信息的
new/delete 比 malloc/free 要成对使用,free释放new出来的对象会导致无法析构而出错。delete释放malloc出来的内存,理论上不会出错,但是程序可读性会变差
delete和delete[]的区别
1 | int *a = new int[10]; |
上面这种情况中的释放效果相同,原因在于:分配简单类型内存时,内存大小已经确定,系统可以记忆并且进行管理,在析构时,系统并不会调用析构函数。
如果 ptr 代表一个用new申请的内存返回的内存空间地址,即所谓的指针,那么:delete ptr 代表用来释放内存,且只用来释放 ptr 指向的内存。delete[] rg 用来释放rg指向的内存,!!还逐一调用数组中每个对象的destructor!!
对于像 int/char/long/int*/struct 等等简单数据类型,由于对象没有 destructor ,所以用 delete 和 delete []是一样的。但是如果是 C++ 对象数组就不同了!
1 | class A |
关于 new[] 和 delete[],其中又分为两种情况:
- (1) 为基本数据类型分配和回收空间;
- (2) 为自定义类型分配和回收空间;
对于 (1),上面提供的程序已经证明了 delete[] 和 delete 是等同的。但是对于 (2),情况就发生了变化。
例子:
1 |
|
结果:
1 | Create a babe to talk with me |
只使用 delete 的时候只出现一个 Babe don’t go away,listen to me
,而使用 delete[] 的时候出现 3 个 Babe don’t go away,listen to me
。不过不管使用 delete 还是 delete[] 那三个对象的在内存中都被删除,既存储位置都标记为可写,但是使用 delete 的时候只调用了 pbabe[0] 的析构函数,而使用了 delete[] 则调用了 3 个 Babe 对象的析构函数。
反正不管怎样都是把存储空间释放了,有什么区别呢?
关键在于调用析构函数上。此程序的类没有使用操作系统的系统资源(比如:Socket、File、Thread等),所以不会造成明显恶果。如果你的类使用了操作系统资源,单纯把类的对象从内存中删除是不妥当的,因为没有调用对象的析构函数会导致系统资源不被释放,这些资源的释放必须依靠这些类的析构函数。所以,在用这些类生成对象数组的时候,用 delete[] 来释放它们才是王道。而用 delete 来释放也许不会出问题,也许后果很严重,具体要看类的代码了。