上篇C++57个入门知识点_25 new与delete(对于对象: new创建时先分配堆内存后调用构造函数,delete先调用析构,后释放堆空间;malloc和free只是堆内存操作,不会调用构造和析构)介绍了C++中new
和delete
的基本用法,本篇将会介绍其使用的注意事项。
总结:
- 当使用基本数据类型的时候,
new
和delete
,malloc
和free
是可以相互替换的 - 当申请一个堆上的对象时,使用
new
和delete
需要配对,不能用malloc
和free
替换 new[]
分配数组,delete[]
释放数组空间new[]
与delete[]
要配套使用(特别是申请对象数组时)- VS编译器会在
new[]
申请对象数组时,在堆开始前的4个字节,写入当前数组的长度,用于记录delete[]
释放时,析构调用次数。
1. new和delete,malloc和free区别及是否可以混用?
(1) 当使用基本数据类型的时候,new
和delete
,malloc
和free
是可以相互替换的
(2) 当申请一个堆上的对象时,使用new
和delete
需要配对,不能用malloc
和free
替换
1.1 new和delete,malloc和free在基本数据类型的混用
- 将
new
和free
混用
int main(int argc, char* argv[])
{
//使用new int(123)赋初值
int* pN = new int(123);
free(pN);
return 0;
}
运行结果:free
实现对堆空间的释放
malloc
和delete
混用
int main(int argc, char* argv[])
{
int* pN = (int*)malloc(sizeof(int));
delete pN;
return 0;
}
运行结果:堆空间得到释放
1.2 new和delete,malloc和free在对象操作时的混用
上面是对基本数据类型操作,看起来是可以混用的,那么针对对象的操作可以混用吗?
new
创建对象,free
释放对象
int main(int argc, char* argv[])
{
//在堆上创建一个对象
CStudent* pStu = new CStudent;
//判断对象是否为空,不为空则进行释放
if (pStu != nullptr) {
free(pStu);
}
return 0;
}
运行结果:对象的内存被释放
new在创建空间的时候会调用构造函数,delete时会调用析构函数,再释放空间。上述过程 new
创建时调用了构造函数,但是free
释放对象时没有调用析构函数。
- 使用
malloc
和delete
混用也是类似的,malloc
创建对象空间,delete
时会调用析构函数,并释放空间。
2. 利用new和delete对数组操作
(1) new[]
分配数组,delete[]
释放数组空间
(2) new[]
与delete[]
要配套使用(特别是申请对象数组时)
(3) VS编译器会在new[]
申请对象数组时,在堆开始前的4个字节,写入当前数组的长度,用于记录delete[]
释放时,析构调用次数。
2.1 利用new和delete对基本数据类型数组操作
基本数据类型,不加[]
释放时起到的作用与加[]
效果是一样的。
int main(int argc, char* argv[])
{
//堆上申请分配10个int大小数组
int* pN = new int[10];
delete[] pN;
return 0;
}
2.2 利用new和delete对对象数组的使用操作
- 创建具有10个对象的对象数组,如果使用
delete pStu
进行释放。
int main(int argc, char* argv[])
{
CStudent* pStu = new CStudent[10];
delete pStu;
return 0;
}
运行结果:只析构了一次,且程序出现崩溃
- 创建具有10个对象的对象数组,如果使用
delete[] pStu
进行释放
int main(int argc, char* argv[])
{
CStudent* pStu = new CStudent[10];
delete[] pStu;
return 0;
}
运行结果:内存全部释放,析构10次
- 在堆上创建一个对象数组时,10个对象,构造十次,编译器怎么记录创建对象个数?
查看内存中对象数组开始位置前不是我们之前看到的"fd fd fd fd"
而是"0a 00 00 00"
我们如果将"0a 00 00 00"
改成"08 00 00 00"
时,会发生什么呢?
运行结果如下:析构8次
出现上面结果的原因为:VS编译器会在new[]
申请对象数组时,在堆开始前的4个字节,写入当前数组的长度,用于记录delete[]
释放时,析构调用次数。
3.视频学习地址:C++57个入门知识点_26 new与delete使用注意事项