c++ 内存管理 new expression

基本元素
new
operator new
placement new
array new

一.new和operator new

1.new expression 的操作伪代码

complex * pc = new complex(1,2)

try{
void * mem = operator new(sizeof (complex)); // operator new可以被重载,没有重载的话,调用全局的::operator new
pc = static_cast<complex*>(mem);
pc->complex::complex(1,2); //直接调用 构造函数,部分编译器才可以做的操作
//或者调用 new(p) Complex(1,2) placement new
}
catch(std::bad_alloc){
}

2.operator new的全局版本 (vc版本)

operator new (size_t size,std::nothrow_t &) _THROW0{
void *P;
while((p = malloc(size) == 0){
  _TRY_BEGIN
if(callnewh(size) == 0 ) break; //callnweh由用户自己设定,可能可以释放一些觉得不重要的内存这样在下次malloc中可能可以成功
_CATCH(astd::bad_alloc)  return(0);
_CATCH_END
})
}
  • 第一个参数“必须”是size_t,以接受new expression的以sizeof(T)为实参的调用
  • callnewh(size) 由用户自己设定,可能可以释放一些觉得不重要的内存这样在下次malloc中可能可以成功
  • std::nothrow_t & 保证这个函数不抛出异常,指明这个函数通过返回一个空指针来表明分配失败,而不是抛出异常

3.delete expression

pc-> ~ Complex();
operator delete(pc);

4.array new

int * pi = new int[10] 的内存空间 (默认行为下的内存空间)
屏幕快照 2020-06-02 下午12.38.37.png
  • delete[] 会调用多次析构函数,如果对一个管理堆内存的对象来说会有影响。
  • delete 把指针指向的位置当成一个对象去解析,只会调用一次析构函数,所以并不会造成内存泄漏
  • 必须要有默认构造函数,array没机会给掉带参数的
  • new[]从地地址向高地址new, delete[] 从高地址向低地址delete
  • Debugger Header 在debug模式下出现
  • 头和尾有个cookie,记录整个分配空间的大小(malloc行为,每一次都会有)
  • 内存要16字节对齐,所以添加了 12个字节的填补

二.placement new

1.placement new

处理流程和new expression一样
区别在于对于operator new的调用上

string s;
string* s= new(&s) string("a");

调用void* operator new(size_t,void * start) { return start ;}

string s;
string* s= new(300) string("a");

调用void* operator new(size_t len,size_t extra) { malloc(len+extra) ;}

  • palcement new中调用operator new时,第一个参数是sizeof的值,之后再传递placement new接受的参数
1.placement delete的重载

placement delete的重载可以被自动调用。

每一个new操作都有分配内存,类型转换,调用构造三步操作
如果在调用构造时抛出异常,为了不让之前的分配出的内存泄漏,会自动调用与之对应的operator new的重载形式

operator new(size_size ,long) 会自动调用 void operator delete(void * ,long)
operator new(size_size ) 会自动调用 void operator delete(void *)

如果没有找到对应的重载, 则被视为放弃处理

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。