内容
new的动作
new是关键字。其实是new operator,本身不可重载。
- 申请内存
- new第一步的申请内存调用的是operator new(可看作一个运算符函数),可以重载。
- 调用构造
- 返回地址
delete的动作
delete是关键字。其实是delete operator,本身不可重载。
- 调用析构
- 内存释放
- delete内存释放调用的是operator delete(可看作一个运算符函数),可以重载。
operator new重载
1 2 3 4 5 6
| void* operator new(size_t size) { void* p = malloc(size); cout << "调用了自定义operator new" << endl; return p; }
|
有何作用?
堆上内存:属于是外部资源。
申请/释放外部资源,用户态没有权限访问,内核态才有权限。外部资源很多,比如我们的鼠标、键盘、屏幕。
我们申请/释放资源的过程需要内核态完成,此时,需要从用户态切换到内核态,再做系统调用。
平时接触的系统调用有很多,比如:cout、printf、cin、scanf
应运而生,会出现内存池的概念。C++自带的内存池:_Alloc
内存池是:用户态自己维护的一大段内存。
重载new和delete相当于留下了一个可修改的端口,可以自定义申请、释放内存的动作。这就是重载new和delete的意义所在。
比如,可以自己编写malloc把内存分配到显存中。除了在改变分配内存的不同设备,还可以在这里面进行内存分配动作的统计、标记等,常用于游戏开发、内存池。
但是要知道,C++只允许把分配内存的任务交给程序员自定义,没有开放在重载new中调用构造函数的权限。
operator delete重载
1 2 3 4 5
| void operator delete(void* p) { cout << "调用了自定义operator delete" << endl; free(p); }
|
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
| #include<iostream> using namespace std; class Tmp { public: Tmp() { cout << "Tmp()" << endl; } ~Tmp() { cout << "~Tmp()" << endl; } void* operator new(size_t size) { void* p = malloc(size); cout << "调用了operator new" << endl; return p; } void operator delete(void* p) { cout << "调用了operator delete" << endl; free(p); } }; int main() { Tmp* p = new Tmp();
}
|
作业
- mstring三种:普通的、写时拷贝的、迭代器的
- 刷题
区别
- new是关键字。malloc是函数;
1 2
| int * p = new int(10); int * s = (int*)malloc(sizeof(int));
|
- new不需要类型转换,malloc需要强转
- new自动计算类型大小,malloc需要sizeof
- new先malloc,再构造,再返回指针。malloc只申请内存
- 申请空间失败时
- new抛出
std::bad_malloc
- malloc返回NULL
- new可以申请一组,需要
new[],delete[]。而malloc必须手动指明字节数,free不知道释放的是不是一组。
- 对于内置类型、POD类型,new/malloc可以混用;对于自定义类型能否混用?主要看类型中有没有析构函数,如果有,在
new[]时会记录申请了多少对象,于是在delete[]时可以自动溯源。
- new是运算符,可以进行重载;malloc则不行
- new有三种调用方式;malloc没有
- new可以设置
nothrow不抛异常,返回NULL
set_new_handler