内存分配
在学习C++控制内存分配部分主要区别以下几组函数:
malloc/free、operator new/delete、new operator/delete和placement new/delete
malloc/free与new/delete
二者都可以从堆中申请和分配动态内存,并且二者都必须成对匹配使用,才可以正确完成内存的的申请和释放功能。
区别:
malloc/free是标准库中的函数,只能用来分配内部数据类型。
new/delete是c++编译器自带的操作符,并且new内置了sizeof、类型转换和类型安全检查功能。对象在创建的同时需要自动执行构造函数,对象在消亡之前要自动执行析构函数。由于malloc/free是库函数而不是运算符,不在编译器控制权限之内,不能够把执行构造函数和析构函数的任务分配给malloc/free。因此,需要new和delete运算符,new能完成动态内存分配和初始化工作,delete能完成清理与释放内存工作。
operator new/delete与new operator/delete
new operator/delete 即 new/delete,new用来完成对象的动态内存分配和初始化工作,delete用来完成清理与释放内存工作,operator new/operator delete是位于对应类中的函数,负责内存的分配和释放。
new operator/delete
new operator 在执行对象初始化时会有两个步骤:1、调用operator new为对象分配内存;2、调用对象的构造函数初始化内存;3、返回相应指针
delete operator 执行时,也存在两个步骤:1、调用对象的析构函数销毁对象;2、调用operator delete释放内存;3、让给定指针为空
new operator/delete 不可以被重载,但用户可以在类内部重载operator new函数和operator delete函数。
operator new/ delete
用户可以根据需求对operator new进行重载。重载时:
1、返回类型必须声明为void*;
2、第一个参数类型必须为表达要求分配空间的大小(字节被new调用),类型为size_t;
3、可以带其它参数(new里面参数,传入operator new大小之后的参数列表)。
operator delete 重载时:
1、返回类型为void;
2、参数为需要销毁的对象指针。
class A { ... void* operator new (size_t size, ...){ ... // 具体实现 return ::operator new(size); //调用系统默认的operator new } void operator delete (void* p){ ... // 具体实现 return ::operator delete(p); /调用系统默认的operator delete } }
placement new
placement new 是 operator new 重载的一个版本,它不分配内存,可以将对象创建在已经被分配好的内存中,返回指向目标内存的一个指针,称为定位new。返回繁荣指针不能被删除,需要调用对象的析构函数来销毁,再delete原内存来释放内存。不存在与定位new表达式相匹配的delete表达式。
placement new 使用步骤:
1、提前分配内存;
2、在已分配的内存上调用placement new创建对象;
3、使用对象;
4、使用完毕后调用对象的析构函数,销毁对象;
5、可重复2、3、4步骤反复利用已分配的内存,不再使用内存时,使用delete释放。
class A { ... } void main() { char *buff = new char[sizeof(A)]; // 1、分配内存 A* p = new(buff) A; // 2、在已分配的内存上创建对象 ... // 3、使用对象 p->~A(); // 使用完毕后调用析构函数销毁对象,不释放内存 ... // 可反复使用内存 delete[] buff; // 释放内存 }