01 - C++内存描绘
C++内存描绘
程序被执行后就被称为一个进程
,一个进程可以被划分为很多区域,主要为:
代码区&常量区:进程按照代码区的代码执行,真正的常量也存储在这里。
PS:
const
关键字只是让编译器将变量视为常量,和真正的常量有本质上的区别。栈区:执行函数所需要的空间。当函数执行完毕,对应的栈内存会被销毁。
堆区:进程用来灵活分配内存的地方,只有手动释放时才会销毁内存
静态变量区:用来存储静态变量和全局变量的区域。
- 静态变量:局部作用范围,生命周期长
- 全局变量:会破坏封装性,不推荐使用
栈区是函数执行的区域,堆区是函数内灵活分配内存的地方,二者缺一不可:
- 如果只在栈上运行程序,其运行结束后会销毁内存。
- 如果只在堆上运行程序,由于堆的唯一寻址方式是指针,没有栈就无法使用堆。
Ps:栈区大小一般不超过8M,远远小于堆区。
当我们创建一个变量时:
int i {7};
i是在栈上分配的自动变量,当程序流离开作用域时,会被自动释放。
静态变量,指针和引用
根据上边提到的,变量的存储位置有三种,分别是 静态变量区,栈区 和 堆区。
静态变量
静态变量区在编译时就已经确定地址,存储全局变量和静态变量。
指针
指针都是存储在栈上或堆上,一定有一个地址。本质上来说,指针和普通变量没有区别。
int* ptr {new int};
这行代码在栈上创建指针变量ptr,然后在自由存储区(堆)中分配一个int的内存,并指向它。
int** handle {nullptr};
handle = new int*;
*handle = new int;
指针变量也可以存储在自由存储区中。上面的代码首先声明一个指向int*的指针变量handle,然后分配足够的内存来保存一个指向int的指针,并让handle指向这个指针,最后让这个指针指向一块int内存。handle
也被称为二级指针。
引用
如上可见,指针可以对内存进行灵活操作,有安全隐患,所以引用被发明了,可以看成是被阉割的指针(类型* const
,所以引用必须赋初值,不能设置为空)。编译器不将其视为对象,操作引用相当于操作引用指向的对象,杜绝了其篡改内存的能力。
参考资料
- 飘零的落花 - 现代C++详解
- C++20高级编程