【C++面向对象】12. new/delete 动态分配内存
2026/9/1 11:58:41 网站建设 项目流程

文章目录

  • 【 0. 内存管理 】
  • 【 1. new、delete 】
    • 1.1 new 分配内存
      • 1.1.1 简单类型
      • 1.1.2 检查内存是否分配成功
    • 1.2 delete 释放内存
  • 【 2. 数组的动态内存分配 】
    • 2.1 一维数组
    • 2.2 二维数组
    • 2.3 三维数组
  • 【 3. 对象的动态内存分配 】
  • 【 4. 其他内存管理函数 】
    • 4.1 malloc() 、free()
    • 4.2 memset 内存初始化

【 0. 内存管理 】

  • C++ 程序中的内存分为以下个部分:

    • 栈区(stack):函数内部 声明的所有变量默认都占用栈内存,由编译器自动分配与释放。存放为运行时函数分配的局部变量、函数参数、返回数据、返回地址等。其操作类似于数据结构中的栈。如声明 int a;系统自动在栈空间中为a开辟空间。
    • 堆区(heap):程序中未使用的内存,在程序运行时可用于用户动态分配内存。如C中的malloc以及C++中的new,如果程序员没有释放,程序结束时可能有OS回收。
    • 全局区(静态区static)存放全局变量、静态数据、常量。程序结束后由系统释放。全局区分为已初始化全局区(data)和未初始化全局区(bss)。
    • 常量区(文字常量区):存放常量字符串,程序结束后由系统释放。
    • 代码区:存放函数体(类成员函数和全局区)的二进制代码。
  • 实例
    p1和p2本身是在栈中的,但他们指向的地址是堆空间。

char*p1=(char*)malloc(10);int*p2=newint(10);

【 1. new、delete 】

  • 在 C++ 中,我们可以使用new 运算符给定类型(可以是包括数组在内的任意内置的数据类型,也可以是包括类或结构在内的用户自定义的任何数据类型)的变量在运行时分配堆内的内存,这会返回所分配的空间地址
  • 如果我们不再需要动态分配的内存空间,可以使用delete 运算符删除之前由 new 运算符分配的内存

1.1 new 分配内存

  • 基本语法
newdata-type;

1.1.1 简单类型

  • 基本语法
    定义一个指向 指定类型(这里指向的是double)的指针,然后请求内存,该内存在执行时被分配:
double*pvalue=NULL;// 初始化为 null 的指针pvalue=newdouble;// 为变量请求内存/*或者*/double*pvalue=newdouble;// 创建1个指针,可以指向double类型的变量。
  • 实例
#include<iostream>usingnamespacestd;intmain(){doublen=3.14;double*pvalue=newdouble;//创建1个可以指向double类型的指针pvalue=&n;// 将指针指向ncout<<*pvalue;return0;}

1.1.2 检查内存是否分配成功

  • 如果自由存储区已被用完,可能无法成功分配内存,所以建议检查 new 运算符是否返回 NULL 指针,并采取以下适当的操作:
double*pvalue=NULL;if(!(pvalue=newdouble)){cout<<"Error: out of memory."<<endl;exit(1);}

1.2 delete 释放内存

  • 在任何时候,当我们觉得某个已经动态分配内存的变量不再需要使用时,我们可以使用 delete 操作符释放它所占用的内存,基本语法:
deletepvalue;// 释放 pvalue 所指向的内存
  • 实例
#include<iostream>usingnamespacestd;intmain(){double*pvalue=NULL;// 创建1个指向 null 的double类型指针pvalue=newdouble;// 为变量请求内存*pvalue=29494.99;// 在分配的地址存储值cout<<"Value of pvalue : "<<*pvalue<<endl;deletepvalue;// 释放内存return0;}

【 2. 数组的动态内存分配 】

2.1 一维数组

  • 基本语法:
    通过动态内存分配,申请一个长度为 n 的数组。
int*array=newint[n]//申请堆内存,将指针pvalue指向该内存/* 上面的一行代码可替换为如下: int* array = NULL; // 初始化为 null 的指针 array = new int[n]; // 申请堆内存,将指针array 指向该内存 *///释放内存delete[]array;
  • 实例
    通过动态内存分配 生成一个元素数量为4的一维数组,令 a[i]=i,最后输出数组。
#include<iostream>usingnamespacestd;intmain(){intn=4;int*a=newint[n];//创建1个动态数组afor(inti=0;i<n;++i)a[i]=i;for(inti=0;i<n;++i)cout<<a[i]<<" ";return0;}

2.2 二维数组

  • 基本语法:
    通过动态内存分配,创建一个二维的 mxn 数组。
// 动态分配内存int**array;array=newint*[m];// 上面的两行代码可简化为:int **a=new int *[m];for(inti=0;i<m;i++){array[i]=newint[n];}//释放内存for(inti=0;i<m;i++){delete[]arrary[i];}delete[]array;
  • 实例
    生成一个3行4列的动态数组,令 a[i][j]=i+j,最后输出数组。
#include<iostream>usingnamespacestd;intmain(){intm=3,n=4;// 动态分配内存int**a=newint*[m];for(inti=0;i<n;i++)a[i]=newint[n];// 为数组赋值for(inti=0;i<n;++i){for(intj=0;j<n;++j)a[i][j]=i+j;}// 输出数组for(inti=0;i<n;++i){for(intj=0;j<n;++j){cout<<a[i][j];if(j==n-1)cout<<endl;elsecout<<" ";}}//释放申请的堆内存for(i=0;i<m;i++){delete[]a[i];}delete[]a;return0;}

2.3 三维数组

  • 基本语法:
    通过动态内存分配,创建一个三维的 mxnxh 数组。
// 动态分配内存int***array;array=newint**[m];for(inti=0;i<m;i++){array[i]=newint*[n];for(intj=0;j<n;j++){array[i][j]=newint[h];}}//释放内存for(inti=0;i<m;i++){for(intj=0;j<n;j++){delete[]array[i][j];}delete[]array[i];}delete[]array;
  • 实例:
#include<iostream>usingnamespacestd;intmain(){inti,j,k;// p[2][3][4]int***p;p=newint**[2];for(i=0;i<2;i++){p[i]=newint*[3];for(j=0;j<3;j++)p[i][j]=newint[4];}//输出 p[i][j][k] 三维数据for(i=0;i<2;i++){for(j=0;j<3;j++){for(k=0;k<4;k++){p[i][j][k]=i+j+k;cout<<p[i][j][k]<<" ";}cout<<endl;}cout<<endl;}// 释放内存for(i=0;i<m;i++){for(j=0;j<n;j++){delete[]p[i][j];}delete[]p[i];}delete[]p;return0;}

【 3. 对象的动态内存分配 】

  • 对象的动态内存分配与简单的数据类型类似。
  • 实例:
    为一个包含四个 Box 对象的数组分配内存,构造函数将被调用 4 次,同样地,当删除这些对象时,析构函数也将被调用相同的次数(4次)。
#include<iostream>usingnamespacestd;classBox{public:Box(){cout<<"调用构造函数!"<<endl;}~Box(){cout<<"调用析构函数!"<<endl;}};intmain(){Box*myBoxArray=newBox[4];delete[]myBoxArray;// 删除数组return0;}

【 4. 其他内存管理函数 】

4.1 malloc() 、free()

  • 头文件:
    C:#include <stdlib.h>
    C++ :#include <cstdlib>
  • malloc() 函数从堆(heap)中分配一块指定大小的内存区域,并返回一个指向这块内存的指针。malloc 分配的内存不会被自动初始化,它包含未定义的值。基本语法:
    • size:需要分配的内存大小(以字节为单位)。
    • 成功时,返回指向分配内存的指针, void* 类型,使用时通常需要进行类型转换
      失败时,返回 NULL 或 nullptr(在 C++11 及以后版本中)。
void*malloc(size_t size);
  • free() 函数释放 指针 指向的存储空间,被释放的空间通常被送入可用存储区池。使用 malloc 分配的内存必须使用 free 函数 来释放,不能使用 C++ 的 delete 运算符。释放内存后,将指针设置为 NULL 是一个好习惯,可以防止野指针问题。基本语法:
    • ptr:指向要释放的内存的指针。
    • 无返回值。
voidfree(void*ptr);
  • 例程
int*array=(int*)malloc(10*sizeof(int));// 申请1个足够存储10个整数的内存free(array);//释放该内存
  • malloc/free 和 new/delete 对比
    在 C 语言中的malloc() 函数,在 C++ 中仍然存在,但建议尽量不要使用 malloc() 函数
malloc/freenew/delete
malloc/free 是C/C++的标准库函数new/delete是C++的运算符
malloc申请的堆区内存不会初始化new是内存自动初始化
malloc需要用户计算好字节数来申请空间new自动计算分配空间
malloc函数返回值是void*,在使用时需要进行类型强制转换在 new 后面直接写明类型
malloc申请内存失败会返回一个NULL,在使用的时候必须进行判空new申请内存失败后会抛出异常
对于自定义数据类型,malloc/free只开辟空间(没有初始化),不会调用构造/析构函数对于自定义数据类型,new不只是分配了内存,它还创建了对象。申请、销毁时会触发构造/析构函数。
malloc/free 都是程序员手动从 堆区 申请,然后手动释放new/delete都是程序员手动从 堆区 申请,然后手动释放
  • 实例
#include<iostream>#include<cstdlib>// 包含malloc函数的头文件usingnamespacestd;intmain(){// 分配足够存储10个整数的内存int*array=(int*)malloc(10*sizeof(int));// 检查分配是否成功if(array==NULL){// 如果分配失败,处理错误return-1;}// 使用分配的内存for(inti=0;i<10;++i){array[i]=i*i;// 初始化数组元素}// 打印数组元素for(inti=0;i<10;++i){cout<<"array["<<i<<"]= "<<array[i]<<endl;}// 释放分配的内存free(array);// 注意:只能使用free来释放malloc分配的内存return0;}

4.2 memset 内存初始化

  • 头文件
    C:#include <string.h>
    C++:#include <string>
  • memset()函数是 C 语言标准库中的一个函数,用于将一块内存区域的前 n 个字节中的每个字节设置为指定的值。基本语法:
    • ptr:指向要填充的内存块的指针。
    • value:要设置的值,通常是一个介于0 到 255之间的整数,因为 memset 一次只设置一个字节大小。
    • num:要设置的字节数
    • 返回指向大小为 num 内存块的原始指针 ptr,如果错误发生返回NULL。
void*memset(void*ptr,intvalue,size_t num);
  • 实例
#include<stdio.h>#include<string.h>// 包含 memset 函数的头文件intmain(){charbuffer[5];// 声明一个足够大的字符数组// 使用 memset 初始化 buffer 的前 5 个字节为 '6'memset(buffer,'6',5);// 打印printf("Initialized buffer with '6':\n");for(inti=0;i<5;++i){printf("%c ",buffer[i]);}return0;}

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询