动态分配存储空间以及释放已分配的存储空间
1、对比
分配失败,返回空指针
C:两个函数malloc()与free()
/*
下面是 malloc() 函数的声明。
void *malloc(size_t size)
返回的是void *(无类型)指针,故需要对指针做转换
size:分配的字节数
*/
#include <stdio.h>
#include <string.h>
#include<stdlib.h> //malloc()函数需要的头文件
int main()
{
char *str;
/* 最初的内存分配 */
str = (char *) malloc(15); //分配15个字节,返回指针转换为char*
if(!str){
return -1; //分配失败
}
strcpy(str, "runoob");
/* 重新分配内存 */
str = (char *) realloc(str, 25);
if(!str){
return -1; //分配失败
}
strcat(str, ".com");
free(str); //释放内存
return 0;
}
C++:两个运算符new和delete
对比:new与delete能完成malloc()与free()的功能,并且更为方便和优越
(1)new自动计算要分配的类型大小,不用手动给出要分配的存储区的大小(字节数,malloc()需要手动给出),方便且可避免偶然错误;
(2)new自动返回正确的指针类型,不用对返回指针做类型转换;
(3)可用new将分配的存储空间初始化,调用对应的构造函数?
(4)可用new分配一个对象的存储空间;
(5)可重载与一个类相关的new和delete;
2、注意点
(1)格式:
/* var_type * p;
p= new var_type(初始化);//
delete p;
//或 delete [] p; P指向数组时的形式
*/
//动态分配单个数据
int *p;
p= new int(8);//初始化为8
delete p;
//动态分配数组
float * p;
//p指向数组第一个元素地址,该数组有10个元素,多维数组时要指明各维度大小
//分配数组空间时,不可初始化
p=new float[10];
delete [] p; //释放分配的数组空间
//为对象动态分配存储空间,调用构造函数初始化
class test{
int x,y,z;
test(int a, int b,int c);
~test(){cout<<"销毁对象";}
};
test::test(int a,int b,int c){
x=a;
y=b;
z=c;
}
int main(){
test *p;
p = new test(4,5,6); //调用构造函数初始化
if(!p){
cout<<"内存分配失败";
return -1;
}
delete p; //释放内存
return 0;
}
(2)delete的操作数必须是一个new返回的指针。对不是new得到的任何其他类型的地址类型,使用delete将会导致严重错误。这种错误是运行时的错误,很难调试。
(3)构造函数和析构函数中含new和delete时,可能会引起指针悬挂以及重复释放同一块地址;指向动态分配的同类型指针之间的赋值会引起指针悬挂,要引起注意;
//指向动态地址的指针间的赋值,导致指针悬挂
char* p1,*p2;
p1=new char[10];
p2=new char[10];
strcpy(p1,"sgfjkg");
p2=p1; //由于将p2指向p1指向的地址,p2原指向的地址空间将不可再使用,也无法释放
delete [] p1; //释放p1指向的地址
delete [] p2; //再次释放p1指向的地址
//构造函数与析构函数
//原理一致
(4)重载new与delete,与重载其它运算符一致,分全局重载(全局中覆盖原版本new和delete)和局部重载(只针对特定类型数据类型使用,如类中重载,只对对应类起作用),重载中调用了malloc()和free()