静态内存:局部static对象,类satic成员,全局变量
栈内存:函数内的非static对象
以上由编译器自动创建和销毁。
heap(堆):dynamically allocate(动态分配的对象)
new:在动态内存中为对象分配空间(并进行初始化)CP407
int *pi=new int;//默认初始化
int *pi=new int(12);//直接初始化
auto *pi=new auto(12);//只能有1个值
//一旦分配失败,new不会抛出异常而是返回空指针
int *pi=new (nothrow) int;
E50 何时使用自定义operator new和operator delete
- 检测运行错误:(检测数据写入位置是否正确)
- 需要了解分配区域的详细信息
- 确认影响程序的性能发生在new和dedlete时。(例如缺省的operator new无法保证齐位)
- 希望做额外的事情。
E49 处理内存分配不足
模板类NewHandlerSupport通过类模板函数set_new_handler和operator new按照不同类型,来采取不同的方法处理内存分配的情况。
template<typename T>
class NewHandlerSupport{
pravite:
static std::new_handler currentHandler;
//用于存放类型T的new_handler函数
};
template<typename T>
std::new_handler NewHandlerSupport<T>::currentHandler=0;
//将类型T的new_handler函数初始化为null
set_new_handler接收1个指向错误处理函数的指针(new_handler)。存储输入的指针p,返回先前存储的指针。下次调用operator new失败时调用保存在set_new_handler的函数
typedef void (*new_handler) ();
new_handler set_new_handler(new_new_handler p) throw()//该函数不抛出任何异常
{
std::new_handler oldHandler=currentHandler;
currentHandler=p;
return oldHandler;
}
当operator new无法满足内存申请时,调用new_handler函数负责找到足够的内存。如果目前的new_handler函数无法完成任务,调用set_new_handler函数替换成新的new_handler函数。
template<typename T>
void* NewHandlerSupport<T>::operator new(std::size_t size) throw(std::bad_alloc)
{
NewHandlerSupport h(std::set_new_handler(currentHandler));
return ::operator new(size);//返回全局
}
如果最终无法分配成功,必须先恢复最初的new_handler函数后,再抛出异常。EP245
//CRTP,
//do it for me:为类A生成对应的new_handler函数
class A: public NewHandlerSupport<A>{
…
};
E51 自定义operator new和operator delete的注意事项
- 内存分配不足时调用new-handling函数
- 对于operator new[]分配的内存不需要进行加工
- 由于派生类可能调用基类的operator new
void* Base::operator new(std::size_t size) throw(std::bad_alloc)
{
if(size!=sizeof(Base))
return ::operator new(size);
…
}
- 4.
void* operator new(std::size_t size) throw(std::bad_alloc)
{
using namespace std;
if(size==0) size=1;//分配0字节也能处理
while(ture){
//当内存成功分配或new_handler函数(直接抛出异常)
}
}
delete:通过指针销毁对象并释放内存
- 动态对象的生存周期与其定义所在的作用域无关,在delete之前一直存在。
- 不能重复释放指针。
- 删除null指针是安全的
void operator delete(void* p) throw()
{
if(p==nullptr) return;
…
}
- 4.
void* Base::operator delete(void* p,std::size_t size) throw()
{
if(p==nullptr) return;
if(size!=sizeof(Base)){
::operator new(p);
return;
}
…
}
E52
placement new:除size_t外还有额外的参数
placement delete:当placement new发生异常时,编译器只能调用delete进行取消
注意在声明时不要无意识遮掩其正常版本。EP260