前言:在C语言中,有malloc,realloc,calloc开辟动态内存空间,free销毁动态内存空间。而在C++中,使用new开辟动态内存空间,delete销毁动态内存空间。不仅简化了操作,更为重要的是,解决自定义类型的初始化问题。
目录
- 一.简化操作
- 二.解决自定义类型初始化问题(重点)
- 三.new不检查失败,抛异常
- 1.抛异常
- 2.捕获异常(try catch)
- 四.operator new/operator delete函数
- 1.内置类型
- 2.自定义类型
一.简化操作
用法:
new 类型
delete 指针
创建数组:new 类型[数据个数]
delete[] 指针
编译器会自动计算类型大小,并且不用再强制转换类型。大大简化了操作,但是要记住下面这三句话:一定要匹配使用!匹配使用!匹配使用!
//int* a = (int*)malloc(sizeof(int));
//free(a);
int* a = new int;
delete a;
int* b = new int[10];
delete[] a;
二.解决自定义类型初始化问题(重点)
new/delete 和malloc/free最大的区别就是new/delete对于自定义类型除了开空间以外会去调用它们的构造函数/析构函数。
new会调用构造函数,delete会调用析构函数。
以栈类为例:
typedef int DataType;
class Stack {
public:
Stack(int capacity = 4)//构造函数
{
_arr = new DataType[capacity];
_capacity = capacity;
_size = 0;
}
void StackPush(DataType Data)
{
_arr[_size] = Data;
_size++;
}
~Stack() //析构函数
{
delete[] _arr;
_capacity = _size = 0;
}
private:
DataType* _arr;
int _capacity;
int _size;
};
int main()
{
Stack* ptr = (Stack*)malloc(sizeof(Stack)); //malloc开辟一个自定义的栈对象
ptr->StackPush(1); //压栈
free(ptr);
return 0;
}
控制台显示如下:我们知道不为0代表着程序出错,那上面代码为什么出错呢?这就是我们强调的malloc只是单纯的开辟空间,不会去调用自定义类型Stack的构造函数,也就没有初始化,没有初始化还向里面压栈肯定会出现错误的。
改成new和delete则不会报错:
int main()
{
Stack* ptr = new Stack;
ptr->StackPush(1);
delete ptr;
//free(ptr) 不行,free不会去调用析构函数,资源得不到清理。
return 0;
}
三.new不检查失败,抛异常
我们用malloc开辟空间时,一般都会写一个if条件语句防止开辟空间失败,而new不再检查失败,出错时会直接抛异常,也就是说用new的话不需要再写if条件防止开辟空间失败。
void Func()
{
//malloc
int* a = (int*)malloc(sizeof(int)*10);
if (a == nullptr) //if判断
{
return;
}
free(a);
//new
int* b = new int[10];
delete[] b;
}
1.抛异常
用malloc开辟同样大小的空间并不会提示错误,而new会。
2.捕获异常(try catch)
利用try和catch捕获异常,找到出现异常的原因。
int main()
{
try
{
char* p2 = new char[0x7fffffff];
}
catch (const exception& error)
{
cout << error.what() << endl;
}
控制台显示如下:
出现异常后会发生执行流跳跃,不执行异常后的代码:
int main()
{
try
{
cout << "正常" << endl;
char* p2 = new char[0x7fffffff];
cout << "异常" << endl;
}
catch (const exception& error)
{
cout << error.what() << endl;
}
return 0;
}
控制台输出如下:可以看到,输出“异常”的代码并没有被执行。这点类似goto语句,出现异常之后,就直接跳到catch语句。这样的设计避免了出错了还运行后面的语句,防止错上加错。
四.operator new/operator delete函数
new和delete是用户进行动态内存申请和释放的操作符,operator new和operator delete是系统提供的全局函数,new在地城调用operator new全局函数来申请空间,delete在底层通过operator delete全局函数来释放空间。
operator new是malloc函数的封装,也就是说,new出来的空间实际上是malloc出来的。不同的是,malloc函数出现错误会返回NULL,而C++需要的是出现错误返回异常,因此封装malloc函数,但出现错误返回异常。
operator delete原理与operator类似。
如下:operator new/operator delete使用方法与malloc/free相同。
int* a = (int*)malloc(sizeof(int) * 10);
free(a);
int* b = (int*)operator new(sizeof(int) * 10);
operator delete(b);
1.内置类型
由上,如果申请的是内置类型的空间,new和malloc,delete和free基本类似。不同的是:new/delete申请和释放的是单个元素的空间,new[]和delete[]申请和释放的是连续空间,而且new在申请空间失败时会抛异常,malloc会返回NULL。
以下三种方式都可以释放空间,实际上都是使用free释放空间。但是第一第二种并不推荐。使用时一定要匹配使用。以避免特殊情况出现。
int* a = new int[10];
//都可以释放申请的空间
//free(a);
//delete a;
delete[] a;
2.自定义类型
- new的原理
1.调用operator new函数申请空间
2.在申请的空间上执行构造函数,完成对象初始化。- delete的原理
1.在空间上执行析构函数,完成对象中资源的清理工作。
2.调用operator delete函数释放对象的空间。- new T[n]的原理
1.调用operator new[]函数,在operator new[]中实际调用operator new函数完成n个对象空间的申请。
2.在申请的空间上执行n次构造函数。- delete[]的原理
1.在释放的对象空间上执行n次析构函数,完成n个对象中资源的清理工作。
2.调用operator delete[]释放空间,实际在operator delete[]中调用operator delete来释放空间。
文末BB:对哪里有问题的朋友,尽管在评论区留言,若哪里写的有问题,也欢迎朋友们在评论区指出,博主看到后会第一时间确定修改。最后,制作不易,如果对朋友们有帮助的话,希望能给博主点点赞和关注.