内存管理基础

C++中可以访问的内存,通常可以分为三类:静态常量区、调用栈和堆。通常编译器使用三块独立内存:一块用于静态变量(可能再细分),一块用于自动变量,另一块用于动态存储。

静态变量区

这一块内存用于静态变量。静态变量区是编译器在编译期间就已经确定好的数据。例如在全局范围内声明const char text[] = "Hello World!",字符串text就会被存放在静态变量区。

特点

  1. 只读;
  2. 大小固定;
  3. 无法管理;
  4. 可以利用其特性在逻辑上做一些特定的优化。

调用栈

这一块内存用于自动变量。

特点

  1. 被动分配,被动回收;
  2. 大小在运行时有一个动态调整的过程;
  3. 大小有系统限制;
  4. 底大顶小。

问题

  1. 为什么变量有作用域?

防止不同的变量使用相同的栈内存,导致后面的变量覆盖前面的数据,从而在使用前面的变量时输出后面的变量。所以设置作用域,使变量出了作用域不再有效。

  1. 为什么不建议使用递归?

因为栈内存是一个非常珍贵的资源,而使用递归有时会产生死循环,将消耗栈内存,直至消耗完,从而产生StackOverflow的错误。

注意

  1. 栈内存先进后出,轮流使用。

同一块内存要在占用它的函数执行完毕,内存被回收之后,其它函数才能使用这一块内存。栈中的内存可以被轮流使用,这也是为什么正常的程序可以一直执行,而不会出现栈溢出的问题。

  1. 不要在函数体中声明大块内存(大型数组,大型结构体)。

例如声明int arr[10240000],十分占用栈内存。栈内存十分珍贵,应避免这种情况。

这一块变量用于动态存储。

特点

  1. 堆大小较大;
  2. 主动分配,主动回收。

分配

分配方式 回收方式
malloc/calloc free
new delete
new T[] delete[] T

示例

/* c 风格, 分配方式 1. */
void * mem = malloc(1024);
/* c 风格, 分配方式 2.*/
void * mem = calloc(1024);
/* C 风格, 回收内存. */
free(mem);

int * iptr = new int; // cpp new
delete iptr;          // cpp delete

int * iarrptr = new int[1024]; // cpp new T[]
delete[] iarrptr;              // cpp delete[] T

注意

  1. 不用堆内存时,一定要及时调用回收API回收内存。
  2. 访问申请的内存时不要超过申请的量,例如 int * ptr = new int[4]; ptr[8] = 0;否则会出现一系列未定义行为Undefined behavior。

指针

指针表示的时某块数据在内存中的地址,地址为整型,它能表示的范围因平台的不同而不同。

程序类型 指针位数 等同于
32位程序 32 uint32_t
64位程序 64 uint64_t

在同一平台上,任何一个指针都可以退化为整数表示,因为任何指针的本质都是一个整数,它代表着一个内存位置。

基本操作

  1. 赋值
  2. 强制转换
  3. 解引用
  4. 加减
int * ptr = new int;
int * iptr = ptr;       // 1. 相同类型的指针直接赋值.
char * c = (char *)ptr; // 2. 不同类型的指针需要强制转换.

int i = *ptr; // 3. 解引用, 将内存 ptr 指向的内存中的内容赋值给变量 i.

// 4. 加减. 指针的加减单位是以指针类型为依据的, int 在内存中占用 4 个字节, testPtr 加减每次的单位也是 4.
// sizeof(int) == 4;
int * arrPtr = new int[4];
int * testPtr = arrPtr;
printf("%u\n", testPtr); // 可将指针作为无符号整型输出.
testPtr = testPtr + 1;
printf("%u\n", testPtr);
testPtr = testPtr + 1;
printf("%u\n", testPtr);

指针,指向指针的指针,指向指针的指针的指针

视频链接

  1. (含字幕)C++ 让你不再害怕内存和指针 其一_哔哩哔哩 (゜-゜)つロ 干杯~-bilibili
  2. [(含字幕)C++ 让你不再害怕内存和指针 其二_哔哩哔哩 (゜-゜)つロ 干杯~-bilibili](
posted @ 2020-12-03 19:42  本丘克  阅读(118)  评论(0编辑  收藏  举报