new/delete 进一步探讨

一、new/delete 的过程

A* pa = new A();
  operator new();  // 其中调用malloc来分配内存
  A::A();

delete pa;
  A::~A();
  operator delete(); // 其中调用free释放内存

new/delete(malloc/free)  释放内存时,也会做一些合并旁边空闲内存块的操作,将零散的内存块合并成更大的内存块。其内部工作很复杂。

而且分配了内存之后还会在这块内存附近记录分配的内存大小,在delete的时候,只是传入要释放的内存块首地址,内存的大小信息存放在这块内存块周围

new一个对象主要会分配哪些内存:
char
* p = new char[10]; 1、记录分配了多少个字节的数字(4字节) 2、Debug模式下可能会有一些调试信息,占用一些字节(30-60字节) 3、分配出去的内存(10字节)(返回的指针地址为该段内存的地址)
注意:如果是对象数组,还会在这块内存前,分配一个4字节的内存,用来记录数组的元素个数,执行几次构造和析构,都是通过这个数字来记录的
4、其他一些必要的信息,一些为提高效率进行边界调整的字节填充(十—几十字节) 5、尾信息,用于回收内存时当作内存尾标记(4字节)

分配一块内存还会附加一些其他的内存,所以频繁的分配小块内存,则很浪费

 

二、重载  operator new/delete  和  operator new[]/delete[]  

class A 
{
public:
    static void* operator new(size_t size);  // size分配的内存大小
    static void operator delete(void* pa);

    static void* operator new[](size_t size);  // size分配的内存大小
    static void operator delete[](void* pa);
};

void* A::operator new(size_t size)  // 这个size是系统根据类的大小指定的
{
    // 下面是必须要做的事情,也是系统默认做的事情
    // 不分配内存会报错
    A* pa = (A*)malloc(size);
    return pa;
}
void A::operator delete(void* pa)
{
    free(pa);
}


void* A::operator new[](size_t size)  // 这个size = 所有类的大小之后 + 4字节(用于存储数组个数)
{
    // malloc 分配的内存包括储存数组个数的数字,但是分配到用户手中的不包含这个数字的内存
    // 比如空类大小为1,这时候size传入的是7,但是分配到用户手中的大小还是3
    A* pa = (A*)malloc(size);
    return pa;
}
void A::operator delete[](void* pa)
{
    free(pa);
}

void fun(){

// 如果自己已经写了operator new和delete还想调用系统的。则可以写成
A* pa = ::new A();   // :: 全局运算符,表示调用系统的new运算符
::delete pa;

A* pb = new A[3]();   // 构造函数被调用了3次,operator new[]/delete[]只被调用了一次
delete[] pb;

}

 

posted @ 2020-07-01 21:13  min_zhi  阅读(163)  评论(0编辑  收藏  举报