多种专业网站建设,小程序源码大全,促销方案,建设网站一般要多少钱C 程序中的内存分为栈和堆两个部分#xff1a;
栈#xff1a;在函数内部声明的所有变量都将占用栈内存#xff1b;堆#xff1a;这是程序中未使用的内存#xff0c;在程序运行时可用于动态分配内存。 堆与栈的详细请参考#xff1a;一文读懂堆与栈的区别_堆和栈的区别_恋… C 程序中的内存分为栈和堆两个部分
栈在函数内部声明的所有变量都将占用栈内存堆这是程序中未使用的内存在程序运行时可用于动态分配内存。 堆与栈的详细请参考一文读懂堆与栈的区别_堆和栈的区别_恋喵大鲤鱼的博客-CSDN博客 由于很多时候无法提前预知存储某个定义变量中的特定信息需要多少内存所需内存的大小需要在运行时才能确定。因此在 C 中可以使用 new 运算符为给定类型的变量在运行时分配堆内的内存并返回所分配空间的地址。当不再需要动态分配的内存空间时使用 delete 运算符释放之前由 new 运算符分配的内存。
new 和 delete 运算符 使用 new 运算符动态分配任意数据类型内存的通用语法
new Data_Type; Data_Type 是包括数组在内的任意内置的数据类型也可以是包括类或结构在内的自定义的任何数据类型。例如定义一个指向 double 类型的指针然后请求内存该内存在执行时被分配
double* pvalue NULL; // 初始化为 null 的指针
pvalue new double; // 为变量请求内存
//也可以直接分配并赋值给指针double* pvalue new double; 当不再需要已经动态分配内存的变量时使用 delete 操作符释放它所占用的内存注意pvalue指针变量本身并没有被销毁销毁的是它指向的变量如下所示
delete pvalue; // 释放 pvalue 所指向的内存 如果自由存储区已被用完可能无法成功分配内存。所以建议检查 new 运算符是否返回 NULL 指针并采取以下适当的操作
double* pvalue NULL;
if(!(pvalue new double)) // 返回 NULL 指针
{cout Error: out of memory. endl;exit(1);
} 演示使用 new 和 delete 运算符
#include iostream
using namespace std;int main ()
{double* pvalue NULL; // 初始化为 NULL 的指针pvalue new double; // 为变量请求内存*pvalue 10086.11; // 在分配的地址存储值cout Value of pvalue : *pvalue endl;delete pvalue; // 释放内存return 0;
} 执行结果如下 Value of pvalue :10086.1 malloc() 函数在 C 中仍然存在但建议尽量不要使用 malloc() 函数。new 与 malloc() 函数相比其主要的优点是new 不只是分配了内存它还创建了对象。
数组的动态内存分配
一维数组 假设为一个能存储 20 个字符的一维数组动态分配内存如下所示
char* pvalue NULL; // 初始化为 null 的指针
pvalue new char [20]; // 为变量请求内存 删除创建的数组语句如下
delete [] pvalue; // 删除 pvalue 所指向的数组
二维数组 例如下面是一个二维数组a[3][4]包含 3 行和 4 列 二维数组array[m][n]:
/* 假定数组array[m][n]第一维长度(行)为 m第二维长度(列)为 n */
int** array; // 声明一个指向int类型指针的指针
array new int *[m]; // 分配m个存储int*类型的空间array指向第一个存储int*的地址/* 为每一行分配空间 */
for( int i0; im; i )
{array[i] new int [n];
}/* 释放每一行 */
for( int i0; im; i )
{delete [] array[i];
}delete [] array; 实例
#includeiostream
using namespace std;int main()
{int **a;int i,j;a new int *[4];for(i0;i4;i){a[i]new int [8];}for(i0;i4;i) // 初始化数组{for(j0;j8;j){a[i][j]((i1)*(j1));}}for(i0;i4;i) // 打印数组数据{for(j0;j8;j){ couta[i][j]\t;if((j7)(i!3)) // 每行8个再换行coutendl; }}for(i0;i4;i) // 释放分配的内存{delete [] a[i];}delete [] a;return 0;
} 执行结果如下 1 2 3 4 5 6 7 8 2 4 6 8 10 12 14 16 3 6 9 12 15 18 21 24 4 8 12 16 20 24 28 32 三维数组
/* 假定数组第一维为 m 第二维为 n 第三维为 h */
int ***array;
array new int **[m];for( int i0; im; i )
{array[i] new int *[n];for( int j0; jn; j ){array[i][j] new int [h];}
}for( int i0; im; i ) //释放内存
{for( int j0; jn; j ){delete[] array[i][j];}delete [] array[i];
}delete[] array; 实例
#includeiostream
using namespace std;int main()
{int i,j,k; // a[2][3][4]int ***a;a new int **[2];for(i0;i2;i) {a[i]new int *[3];for(j0;j3;j){a[i][j]new int [4];}}for(i0;i2;i) //初始化并输出{for(j0;j3;j){for(k0;k4;k){a[i][j][k] ijk;couta[i][j][k] ;}coutendl; }coutendl;}for(i0;i2;i) //释放内存{for(j0;j3;j){delete [] a[i][j];} }for(i0;i2;i){delete [] a[i];}delete [] a;return 0;
} 执行结果如下 0 1 2 3 1 2 3 4 2 3 4 5 1 2 3 4 2 3 4 5 3 4 5 6 补充由于对象没有析构函数(destructor)“ delete [] p ”和 “ delete p ” 对于像 int/char/long/int*/struct 等简单数据类型的释放没有太大区别。但对于C 对象数组就不同了
delete a; 仅释放了a指针指向的全部内存空间 但是只调用了a[0]对象的析构函数其他分配的内存空间将不能释放从而造成内存泄漏delete [] a; 调用使用类对象的析构函数释放用户自己分配内存空间并释放了a指针指向的全部内存空间。
对象的动态内存分配 对象与简单的数据类型没有什么不同如下所示为一个包含3个 Box 对象的数组分配内存构造函数将被调用 4 次。当删除这些对象时析构函数也将被调用相同的次数
#includeiostream
using namespace std;class Box
{
public:Box(){cout调用构造函数endl;}~Box(){cout调用析构函数endl;}
};int main()
{Box* BoxArray new Box[3];delete [] BoxArray;return 0;
} 执行结果如下 调用构造函数 调用构造函数 调用构造函数 调用析构函数 调用析构函数 调用析构函数 new 和 malloc 的区别 new 的功能是在堆区新建一个对象并返回该对象的指针。 新建对象 的意思就是将调用该类的构造函数因为如果不构造的话就不能称之为一个对象。 malloc 只是机械的分配一块内存用 mallco 在堆区创建一个对象不会调用构造函数。严格说来用 malloc 不能算是新建了一个对象只能说是分配了一块与该类对象匹配的内存而已然后强行把它解释为 “这是一个对象”因此也不存在调用构造函数的说法。 同样的用 delete 去释放一个堆区的对象会调用该对象的析构函数。 用 free 去释放一个堆区的对象不会调用该对象的析构函数。 实例:
#include iostream
#include malloc.h // 需要用到malloc()函数using namespace std;class Test
{
private:int num1;int num2;
public:Test(){num1 10;num2 20;} void Print(){coutnum1\t num2endl; }
};int main()
{/****用malloc()函数在堆区分配一块内存空间然后用强制类型转换将该块内存空间*解释为是一个Test类对象但不会调用Test的默认构造函数 */ Test* pObject1 (Test*)malloc(sizeof(Test));pObject1-Print();/* 用new在堆区创建一个Test类的对象会调用Test类的默认构造函数 */Test* pObject2 new Test;pObject2-Print();return 0;
} 由于pObject1没有调用Test类的默认构造函数所以在pObject1所指的对象中num1与num2都是malloc()分配地址上原有的垃圾值并非是由构造函数定义的初始值(10 or 20)。而pObject2所指的对象中num1与num2显然是经过了构造后的值执行结果如下 1922960 0 10 20