1.C++内存管理方式
C语言内存管理方式在C++中可以继续使用,但有些地方就无能为力,而且使用起来比较麻烦,因此C++又提出了自己的内存管理方式:通过new和delete操作符进行动态内存管理。
1.1 new/delete操作内置类型
1.1.1基本代码实现
#include<iostream>
using namespace std;
int main()
{
// 1.malloc/calloc/realloc的区别:(C语言)
//int* p1 = (int*)malloc(40);
//int* p2 = (int*)calloc(4, sizeof(int));
//int* p3 = (int*)realloc(p2, sizeof(int) * 10);
// C++
// 动态申请一个int类型的空间
int* ptr4 = new int;
//动态申请一个int类型的空间
int* ptr5 = new int(1);
// 动态申请10个int类型的空间
int* ptr6 = new int[10];
int* ptr7 = new int[10] {1, 2, 3}; //超出来的用0初始化
//delete时, 上面New的时候有[]就要带上[]
delete ptr4;
delete ptr5;
delete[] ptr6;
delete[] ptr7;
return 0;
}
注意:申请和释放单个元素的空间,使用
new
和
delete
操作符,申请和释放连续的空间,使用
new[]
和
delete[]
,注意:匹配起来使用。
1.1.2原理
原理简单来说,就是开辟失败后会抛异常,被catch抓住,可以先看代码简单了解一下:
#include<iostream>
using namespace std;
double Divide(int a, int b)
{
//当b == 0时抛出异常
if (b == 0)
{
string s("Divide by zero condition!");
throw s;
}
else
{
return ((double)a / (double)b);
}
}
int main()
{
try
{
int len, time;
cin >> len >> time;
cout << Divide(len, time) << endl;
}
catch (const string& s)
{
cout << s << endl;
}
return 0;
}
1.1.3计算堆区大概有多少空间
注意:我们用x86环境,x64的堆区太大了,比较浪费时间!
代码如下:
#include<iostream>
using namespace std;
void func()
{
int i = 1;
while (1)
{
int* p1 = new int[1024 * 1024];
cout <<i<< "->" << p1 << endl;
i++;
}
}
int main()
{
try
{
func();
}
catch (const std::exception& e) //exception就是异常的意思,其在std类下,详情可以查看c++函数文档
{
cout << e.what() << endl;
}
return 0;
}
结果如下:
1.2 new和delete操作自定义类型
new/delete
和
malloc/free
最大区别是
new/delete
对于【自定义类型】除了开空间
还会调用构造函数和析构函数
内置类型是几乎是一样的
#include<iostream>
using namespace std;
class A
{
public:
A(int a1 = 0, int a2 = 0)
:_a1(a1)
, _a2(a2)
{
cout << "A():" << this << endl;
}
~A()
{
cout << "~A():" << this << endl;
}
private:
int _a1;
int _a2;
};
int main()
{
//A* p1 = (A*)malloc(sizeof(A)); //屏幕上没有打印结果
//A* p2 = new A(1, 1); //结果:A():008A1C18
//free(p1); //屏幕上没有打印结果
//delete p2; //结果:~A():008A1C18
//A* p5 = (A*)malloc(sizeof(A)*10);
//A a1(1), a2(2), a3(3);
//A* p6 = new A[3]{ a1,a2,a3 };
//A a1 = { 1,1 };
//A* p6 = new A[10]{ {1,1},{2,2},{3,3} };
A* p6 = new A[10];
//free(p5);
delete[] p6;
return 0;
}
注意:在申请自定义类型的空间时,
new
会调用构造函数,
delete
会调用析构函数,而
malloc
与
free
不会
。
2. operator new与operator delete函数
2.1 operator new与operator delete函数
new
和
delete
是用户进行
动态内存申请和释放的操作符
,
operator new
和
operator delete
是
系统提供的
全局函数
,
new
在底层调用
operator new
全局函数来申请空间,
delete
在底层通过
operator delete
全局函数来释放空间。
operator new
:该函数实际通过
malloc
来申请空间,当
malloc
申请空间成功时直接返回;申请空间
失败,尝试执行空 间不足应对措施,如果改应对措施用户设置了,则继续申请,否则抛异常。
如果申请内存失败了,这里会抛出
bad_alloc
类型异常
operator delete:
该函数最终是通过
free
来释放空间的
本质上,operator new
实际也是通过
malloc
来申请空间
,如果malloc申请空间成功就直接返回,否则执行用户提供的空间不足应对措施,如果用户提供该措施就继续申请,否则就抛异常。operator delete
最终是通过
free
来释放空间的
。
3 malloc/free和new/delete的区别
malloc/free
和
new/delete
的共同点是:都是从堆上申请空间,并且需要用户手动释放。不同的地
方是:
1. malloc
和
free
是函数,
new
和
delete
是操作符
2. malloc
申请的空间不会初始化,
new
可以初始化
3. malloc
申请空间时,需要手动计算空间大小并传递,
new
只需在其后跟上空间的类型即可,
如果是多个对象,
[]
中指定对象个数即可
4. malloc
的返回值为
void*,
在使用时必须强转,
new
不需要,因为
new
后跟的是空间的类型
5. malloc
申请空间失败时,返回的是
NULL
,因此使用时必须判空,
new
不需要,但是
new
需
要捕获异常
6.
申请自定义类型对象时,
malloc/free
只会开辟空间,不会调用构造函数与析构函数,而
new
在申请空间后会调用构造函数完成对象的初始化,
delete
在释放空间前会调用析构函数完成
空间中资源的清理释放