new和delete的重载

new和delete是管理堆内存的开辟和释放

如果你想在进程的全局范围内,实现一个内存池的话,你可以通过重载operator new和operator delete做内存的开辟和释放。

new和delete的重载

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#include <bits/stdc++.h>
using namespace std;
void *operator new(size_t size)//函数完成后,会紧接着调用构造函数
{
void *p=malloc(size);
if(nullptr==p)
{
throw bad_alloc();//new开辟内存失败,抛出bad_alloc类型的异常对象
}
cout<<"operator new size:"<<size<<" addr:"<<p<<endl;
return p;
}
//先调用对象的析构函数,delete释放内存
void operator delete(void *ptr)
{
cout<<"operator delete addr"<<ptr<<endl;
free(ptr);
}
//数组开辟
void *operator new[](size_t size)//函数完成后,会紧接着调用构造函数
{
void *p=malloc(size);
if(nullptr==p)
{
throw bad_alloc();//new开辟内存失败,抛出bad_alloc类型的异常对象
}
cout<<"operator new[] size:"<<size<<" addr:"<<p<<endl;
return p;
}
//数组释放
void operator delete[](void *ptr)
{
cout<<"operator delete[] addr"<<ptr<<endl;
free(ptr);
}
class test
{
public:
test(){cout<<"test()"<<endl;}
~test(){cout<<"~test()"<<endl;}
private:
int ma;
};
int main()
{
test *p=new test;
delete p;
test *p1=new test[5];
delete []p1;
return 0;
}

结果(注意要在Linux环境下编译运行)

从这个结果可以看出new了5个int类型的对象,却发现size是28,这是因为在内存起始地址还会有一个内存存储数组对象的个数,所以size是28(32位系统占4个字节,64位系统占8个字节)

1、怎么防止内存泄漏

​ 智能指针

2、为了防止发生内存泄漏,你在代码应该怎么处理

1
2
3
4
5
vector<void *>vec;
operator new
operator delete
当开辟空间时,把开辟的内存地址addr添加到vec里面然后delete
最后所有的操作完成之后,打印vec,如果vec是空的,则证明没有发生内存泄漏,否则就证明发生了内存泄漏。并且把这些内存地址全部delete

3、new和delete配对使用,new[]和delete[]配对使用,那什么时候可以混用?

如果是对象类型,而且对象有析构函数,那么开辟对象数组时,会多开辟8个字节存储对象的个数,目的时在delete []p 的时候,知道调用多少次析构函数。

如果是对象类型,而且对象有析构函数需要调用,那么不能混用,如果是内置类型,自定义类型(但是没有析构函数),可以混用。