动态内存申请的区别
c语言的动态内存申请-->由函数申请
-
malloc():不带初始化的
-
calloc():带初始化的,初始化为0
-
realloc():重新申请(在原内存的后面接着申请)
-
free(): 释放
c++的动态内存申请-->由关键字申请
-
只有new(申请)和delete(释放)
-
单个变量内存申请
-
数组的动态内存申请
-
结构体的动态内存申请
单个变量的内存申请
申请单个内存不做初始化
void testOneMemory()
{
//申请一个整型变量的内存,不做初始化,让指针指向一个变量的内存
int*pInt=new int; //申请完内存后,可以当变量来使用
*pInt=123;
cout<<*pInt<<endl; //输出123
}
可以new其他类型,只要注意格式即可
void testOneMemory()
{
//申请一个字符型变量的内存,不做初始化,让指针指向一个变量的内存
char* pChar=new char; //申请完内存后,可以当变量来使用
*pChar='a';
cout<<*pChar<<endl; //输出a
}
申请单个内存时做初始化
//用()可以给单个数据初始化
void testOneMemory()
{
int*pNum=new int(124); //用()给当前申请的整型变量的内存初始化为124
cout<<*pNum<<endl; //输出124
}
单个变量的内存释放
delete pInt;
pInt=nullptr; /*释放后一定要置空,否则指针还是存在,指针指向新的内存还能使用
释放没有置空可以再new一段内存,相当于改变指向*/
pInt=new int;
*pInt=33;
cout<<*pInt<<endl;//new完后还要做一次释放|置空
如何申请一大串内存?用一维数组方式申请
用一维数组方式申请一大串内存不做初始化
void testArrayMemory()
{
//申请一段内存用一维数组方式申请|等效产生了int pInt[3]的数组
int*pInt=new int[3]; /*[]中代表长度,可以是常量|变量,只要是值就可以了
'A'也可以,自动转换成65*/
delete pInt; //这样释放也可以,推荐用下一行代码的方式,增加可读性
delete pInt[]; //用了[]代表当前这个变量是一段内存
pInt[]=pstr; //释放完后置空
}
也可以让用户输入长度
int num=0;
cin>>num;
int* pInt=new int[num];
用字符串处理用strcpy的方式
#include<cstring> //c语言的string
int main()
{
char* pstr=new char[15]; //char* 不能直接赋值
strcpy(pstr,"i love you"); //处理字符串通常用拷贝的方式
//strcpy_s(pstr,15,"ILoveYou"); 增强版
cout<<pstr<<endl; //输出ILoveYou
}
-
char* 不能直接赋值,处理字符串尽量用strcpy的方式
-
"i love you"是指向常量区的内存,没有赋值到堆区上
#include<cstring>
int main()
{
char* pstr=new char[15]; //ptr 不建议直接赋值,这样写数据没有赋值到new char[15]上
pstr="i love you"; /*vs2013这样写不报错,vs2019会报错:const char* 类型的值
不能用于初始化char* 类型的实体*/
//解决方案:const char* pstr=new char[15];
cout<<pstr<<endl;
}
- new char[15](堆区)上没有任何数据,这段内存没有初始化,输出乱码
-
把pstr的指向改变了,不影响pstr申请的内存
#include<cstring>
int main()
{
const char* pstr=new char[15]; //pstr指向new char[15]
const char*pstr1=pstr; //pstr1指向pstr,指向同一块内存ptr
pstr="i love you"; //pstr改为指向"i love you"
cout<<pstr<<endl; //输出:i love you
cout<<pstr1<<endl; //pstr1未做初始化,没有数据,输出乱码
}
用一维数组方式申请一串内存时做初始化- - -一堆数据用{ }的方式
//用{ }可以给一段内存初始化,未初始化的参数默认为0
void testArrayMemory()
{
int*pNum=new int[3]{1,2,3};
for(int i=0;i<3;i++)
{
cout<<pNum[i]<<" "; //输出1 2 3
}
cout<<endl;
delete pNum[];
pNum[]=nullptr; //释放完后置空
}
用字符串方式申请一串内存时做初始化
//字符数组方式初始化
char* str=new char[20]{'A','B','\0'};
cout<<str<<endl; //输出:AB
delete[] str;
str=nullptr;
//直接用字符串的方式初始化
str=new char[20]{"i love you"};
cout<<str<<endl; //输出:i love you
delete[] str;
str=nullptr;
释放有且只有两种方式
- delete 指针:单个变量内存释放
-
delete[ ] 指针:一段内存释放,[ ]中不用填释放长度 & 不存在[ ][ ]的情况 基本语法
结构体动态内存申请
结构体的内存申请不做初始化
struct MM
{
int age;
char* name; //char name[20];
void printstu()
{
cout<<name<<"\t"<<age<<endl;
}
};
void teststructMemory()
{
//new一个对象
int* p=new int; //结构体动态内存申请和整型变量动态内存申请类似
MM* pMM=new MM;
}
结构体申请内存时做初始化
struct MM
{
int age;
const char* name; //const char*类型的值不能用于初始化char*类型的实体 加const修饰
void printMM()
{
cout << name << "\t" << age << endl; //打印字符串不需要加*,只需要首地址即可
}
};
void teststructMemory()
{
//new一个对象
int* p = new int(23);
MM* pMM = new MM{"小明",18}; //报错:未写构造函数前 结构体只能用{ }初始化
pstu->printMM(); //调用成员函数打印一下 输出:小明 18
}
结构体申请内存时做初始化做修改时会出现问题(const导致不能修改数据)
struct MM
{
int age;
const char* name;
void printMM() //成员函数
{
cout<<name<<"\t"<<age<<endl;
}
};
void teststructMemory()
{
//new一个对象
MM* pMM=new MM{"小明",18};
pMM->printMM();
pMM->name=new char[18];
strcpy(pMM->name,"i love you"); //报错:可以给它拷贝了一段内存,但不能修改
}
结构体申请内存后做初始化
char* 类型的指针没有内存,不能拷贝东西进去(用strcpy_s 拷贝,name没有长度)strcpy_s中间的参数是用来描述name的长度的,要做二次申请,才能strcpy或者赋值
struct MM
{
int age;
char* name;
void printMM()
{
cout<<name<<"\t"<<age<<endl;
}
};
void teststructMemory()
{
//new一个对象
MM* pMM=new MM; //先申请内存
pMM->name=new char[20]; //二次申请 给name申请一段内存
strcpy_s(pMM->name,20,"张三");
pMM->age=19;
pMM->printMM();
}
/*输出*/
张三 19
结构体的内存释放
申请和释放顺序相反,先申请,后释放
反过来会中断,出现内存的重复释放,pMM不存在,怎么释放pMM的name?
struct MM
{
int age;
char* name;
void printMM() //成员函数
{
cout<<name<<"\t"<<age<<endl;
}
};
void teststructMemory()
{
//new一个对象
MM* pMM=new MM;
pMM->name=new char[20]; //二次申请 给name申请一串内存
strcpy_s(pMM->name,20,"张三");
pMM->age=19;
pMM->printMM();
delete[]pMM->name;
delete pMM; //1个结构体变量的内存释放
}
结构体中char* 复制字符串为啥要用const?
跟赋值的值有关系,c++对const要求更严格,赋值语句两边类型必须一致
void testConst()
{
char* str = "ILoveYou"; //报错:指针变量指向常量地址,类型不一致 指针变量=常量地址
char str2[] = "ILoveYou";
char* str3 = str2; //不是常量区,是栈区变量,可以直接指向
}
拓展(c语言malloc( )、calloc( )、realloc( )申请内存)
malloc( )
void print(int array[],int arrayNum) //打印数组
{
for(int i = 0;i < arrayNum; i++)
{
cout << array[i] << " ";
}
cout << endl;
}
void testMalloc()
{
//等效于产生了一个数组int pMnum[3]
int* pMnum = (int*)malloc(sizeof(int)*3); //分配内存的大小
if(pMNum == NULL) //申请内存可能失败
return;
memset(pMNum,0,sizeof(int)*3); //内存初始化为0
print(pNum,3); //申请内存不做初始化
}
calloc( )
void testCalloc()
{
int* pCNum=(int*)calloc(3,sizeof(int));
}
/*输出 类似memset的作用*/
0 0 0
void*_cdecl calloc(size_t_Count,size_t_Size) //变量个数|变量大小
realloc( )- - -内存不够,重新申请,原来数据还在
void testRealloc()
{
int* pInt=(int*)malloc(sizeof(int));
if(pMNum==NULL) //申请内存可能失败
return;
*pInt=1999;
pInt=(int*)realloc(pInt,sizeof(int)*3); //原来只有一个变量的内存,现在有3个变量的内存
pInt[1]=123;
pInt[2]=134;
print(pInt,3);
free(pInt);
}
/*输出*/
1999 123 1234