写在前面:此文章持续更新,对C++内存管理的学习进行复习总结。相关学习参考内容已列下方,目前水平有限,如有建议,欢迎指正!
References
- C++与内存管理李罡
变量与内存
1. 声明 VS. 定义
extern int i; // 声明,用到其他源文件的变量
extern int i = 1; // 定义
2. 全局 VS. 局部,静态 VS. 非静态
全局变量:指在函数外定义的变量
局部变量:指在函数内定义的变量
静态变量:指定义时加static关键字的变量
非静态变量:指定义时不加static关键字的变量
上面四种两两组合,出来四种情况:
- 全局静态:在函数外加个static(只能当前一个cpp使用)
- 全局非静态:在函数外加个extern或省略(可以跨cpp使用)
局部变量:定义在函数内,代码块内的变量,函数形参也可视为局部变量。局部变量可以与全局变量重名,此时优先使用局部变量,若想使用全局变量,在变量名前加::
- 局部静态:加static,在整个程序运行中,有且仅有这一个变量,不会被销毁。
- 局部非静态:不加static
静态存储:存放在data区。包括:全局静态、全局非静态、局部静态。生存周期为整个程序运行期间。
自动存储:存放在stack区。包括:局部非静态,参数形参。生存期随代码块自动分配收回。
动态存储:存放在heap区。包括:malloc和new(动态new,非定位new)申请的内存。程序员手工分配回收。(new一堆不delete,内存泄漏,把内存占满了)。
3. 变量初始化 VS. 赋值
int i = 1; //初始化
int i; i = 1; //赋值
const类型的,只能初始化,且必须初始化,不能赋值。
非const类型的变量,既可以初始化,也可以赋值。
初始化:自动(隐式)初始化、显式初始化
静态存储区,自动初始化为0。
自动存储区,不自动初始化。
动态存储区,不自动初始化。
(注意,这三种都是基本数据类型)
对象无论存在哪里,一定会通过构造函数被初始化。
对象初始化问题:对象本身一定被初始化,对象的成员变量不一定被初始化。
成员变量的初始化分为以下几种情况:
- 自动(隐式初始化)
- c++11开始,可以给对象(非静态)成员变量赋初值进行初始化
- 使用初始化列表进行初始化
注意,对于类的静态成员变量,要在类外定义,方可使用。(类内声明,类外初始化)
class A{
static int y;
};
int A::y = 1;
4. 关键词static用法小结
对于全局变量而言,static决定链接性
对于局部变量而言,static决定持续性
对于成员变量而言,static决定是类成员变量还是对象成员变量
动态内存管理
栈,函数专用,当调用函数时,函数的局部变量,传进来的实参(函数的形参)都进栈。
- 动态内存,通过new或malloc()申请的内存,比你实际申请的大。(因为申请的内存,在这块内存头部有一些数or数组相关配置信息)
- 分配与释放成对
new <----> delete
new []<----> delete[]
malloc()<----> free()
注意,申请0长度的array,是可以编译通过的,也需要释放。虽然array的长度为0,但前面还有块配置信息,已经申请好了。
只new不delete会内存泄漏(memory leak) - 实例
plus:当把new出来的空间delete即释放以后,没有处理留在栈空间的指针,成为了野指针。
正确释放方法:
int *p = new int(4);
if (p != NULL)
{
delete p;
p= NULL;
}