【C++】- 内存管理(new和delete详解!!)

内存管理

  • C/C++内存分布
  • new/delete

C/C++内存分布

【C++】- 内存管理(new和delete详解!!)_第1张图片

在计算机的程序内,有不同的内存分区,内存分区是为了有效管理和利用计算机的内存资源而进行的划分,也是因为不同的数据有不同的存储需求,各区域需要满足不同的需求。

我们先大致了解一下常见到的几个内存分区(静态区常量区堆区栈区):

静态区:
静态区(也称为数据段)是程序的一部分,用于存储全局变量和静态变量。在C/C++中,静态变量包括全局静态变量和局部静态变量。

全局静态变量存储在静态区中,并且在整个程序的执行期间都存在。它们在程序启动时被初始化,并且只被分配一次内存。

局部静态变量也存储在静态区中,但是它们只在其所在函数第一次执行时被初始化,并且在函数执行过程中保持其值。与自动变量不同,局部静态变量的生命周期超出函数的作用域。

常量区:
常量区(也称为代码段或只读数据段)是存储程序中的常量数据的一部分。在常见的C/C++实现中,常量区通常位于程序的可执行文件中,并且在程序运行时是只读的,不允许修改。

常量区包括以下类型的数据:

  1. 字符串常量:例如,char2和pChar3都指向的字符串常量"abcd"就存储在常量区中。
  2. 全局常量:全局常量(如全局const变量)的值也存储在常量区中。
  3. 静态常量:静态局部常量(如在函数内部声明为static const的变量)的值也存储在常量区中。

需要注意的是,常量区中的数据是只读的,因此在程序运行过程中不能修改这些数据的值。

但是,对于指针变量(如指向常量区的指针),可以通过改变指针的指向来间接修改常量区中的数据。不过,这样的操作是不安全的,可能会导致未定义的行为,因此应该避免这样做。

总结起来,常量区存储程序中的常量数据,包括字符串常量、全局常量和静态常量。它是只读的,在程序运行时不能修改。

堆区:
堆区是用于动态内存分配的一部分内存空间。它在程序运行时动态地分配和释放内存,用于存储程序中的动态对象。

在C/C++中,通过调用malloc、calloc、realloc等函数来在堆区分配内存。这些函数返回指向分配内存的指针。分配的内存可以使用指针进行访问,并且在不再需要时需要手动调用free函数来释放内存,以防止内存泄漏。

堆区的特点如下:

  1. 动态内存分配:堆区允许在程序运行时根据需要分配和释放内存。
  2. 大小可变:堆区的大小可以根据需要进行动态调整。
  3. 需要手动管理:分配的内存需要手动释放,否则可能导致内存泄漏。
  4. 独立于函数作用域:在堆区分配的内存可以在不同的函数之间共享和访问。

栈区:
栈区是一种用于存储局部变量和函数调用信息的内存空间,它的管理方式类似于一个堆叠。

在函数被调用时,函数的参数和局部变量将会被压入栈中。当函数执行完毕时,这些变量将会从栈中弹出。

栈区的特点如下:

  1. 自动分配和释放:栈区中的内存是由编译器自动分配和释放的,无需手动管理。
  2. 大小固定:栈区的大小是固定的,由系统预先设定,不能根据需要进行动态调整。
  3. 存储局部变量和函数调用信息:栈区主要用于存储局部变量、函数参数和函数调用信息等数据。
  4. 独立于函数作用域:不同函数之间的栈数据是相互独立的,不存在共享关系。

new/delete

在C语言中我们常用malloc、calloc和realloc函数来进行动态内存管理,这种内存管理方式在C++中可以继续使用,但有些地方就无能为力,比如说malloc解决不了动态申请的自定义类型的初始化问题,而且使用起来比较麻烦,因此C++又提出了自己的内存管理方式:通过new和delete操作符进行动态内存管理。

new是C++的关键字,用于在堆上动态分配内存,它可以调用适当的构造函数初始化分配的内存,并返回指向该内存的指针。也就是说的new会做两件事情,一是开空间而是调用构造函数

new的基本语法如下:

new 类型名;

其中类型名可以是任何C++数据类型或用户自定义类型。例如,要分配一个整数变量,可以使用以下代码:

int* p = new int;

也可以使用new来分配数组,例如:

int* a = new int[10];

这将分配包含10个整数的数组,并将第一个元素的地址赋给指针变量a。
在这里插入图片描述

delete 是 C++ 中用于释放通过 new 操作符分配的动态内存的操作符。它的基本语法如下:

delete 指针;

其中,指针是通过 new 操作符返回的指向动态内存的指针。当 delete 操作符被执行时,它会释放指针所指向的动态内存,并调用相应对象的析构函数进行资源清理。

例如,如果通过 new 操作符分配了一个整数对象的内存,可以使用 delete 操作符释放该内存,如下所示:

int* ptr = new int;
// 使用指针进行一些操作
delete ptr;

同样,如果通过 new 操作符分配了一个自定义类对象的内存,也可以使用 delete 操作符释放该内存,这时delete会调用析构函数,如下所示:

MyClass* obj = new MyClass();
// 使用对象进行一些操作
delete obj;

需要注意的是,delete 只能用于释放通过 new 操作符分配的内存。对于栈上或静态内存中的对象,不应该使用 delete 进行释放。

另外,在delete释放指针之后,应该将指针设置为 nullptr,以避免出现悬空指针的情况。例如:

delete ptr;
ptr = nullptr;

看如下一段代码:
【C++】- 内存管理(new和delete详解!!)_第2张图片

申请和释放单个元素的空间,使用new和delete操作符,申请和释放连续的空间,使用
new[]和delete[],注意:匹配起来使用。

总之,new是C++中用于在堆上动态分配内存的关键字,它可以调用构造函数初始化分配的内存,并返回指向该内存的指针。与malloc相比,new更加灵活,能够支持对象的构造和析构,不需要手动计算分配的内存大小。delete 是 C++ 中用于释放通过 new 操作符分配的动态内存的操作符。需要配套new进行使用。

你可能感兴趣的:(c++,java,jvm)