简单的new操作重载以及关于内存的一些体会

时间:2021-12-21 17:36:05

#include<iostream.h>
#include<windows.h>
#include<stddef.h>

class opNew
{
private:
    static HANDLE s_hHeap;
    static UINT s_uNumAllocsInHeap;
public:
    opNew();
    ~opNew();
    void * operator new(size_t size);
    void operator delete(void *p);
};

HANDLE opNew::s_hHeap = NULL;
UINT opNew::s_uNumAllocsInHeap = 0;

opNew::opNew()
{
    cout << "Constructor:" << endl;
    cout << s_hHeap << endl;
    cout << s_uNumAllocsInHeap << endl;
}

opNew::~opNew()
{
    cout << "DeConstructor:" << endl;
    cout << s_hHeap << endl;
    cout << s_uNumAllocsInHeap << endl;
}

void * opNew::operator new(size_t size)
{
    if(s_hHeap == NULL)
    {
        s_hHeap = HeapCreate(HEAP_GENERATE_EXCEPTIONS, 0, 0);
       
        if(s_hHeap == NULL)
            return NULL;
    }

    void *p = HeapAlloc(s_hHeap, HEAP_ZERO_MEMORY, size);
    if(p != NULL)
    {
        s_uNumAllocsInHeap++;
    }

    return p;
}

void opNew::operator delete(void *p)
{
    if(HeapFree(s_hHeap, 0, p))
    {
        s_uNumAllocsInHeap--;
    }

    if(s_uNumAllocsInHeap == 0)
    {
        if(HeapDestroy(s_hHeap))
            s_hHeap = NULL;
    }
}


void test1()
{
    opNew op1;
   
}

void test2
{
    opNew *op1 = new opNew;
    opNew *op2 = new opNew;
    opNew *op3 = new opNew;
   
}

void test3
{
    opNew *op1 = new opNew;
    opNew *op2 = new opNew;
    opNew *op3 = new opNew;
   
    delete op3;
    delete op2;
    delete op1;
}


void main()
{
    test1();
    test2();
    test3();

    system("PAUSE");
}

 

上面只是一个重载new以及delete的简单例子。但是从中我也发现了一些东西。

 

当我们运行程序后,会发现 test1 test3 调用了析构函数。但是test2没有调用。这是为什么呢?

 

1.

opNew op1;

是在栈上位变量分配内存。而在上分配的内存,在出了变量的作用域后会自动销毁。所以test1调用完之后,对象op1也就销毁了,因此会自动调用析构函数。

 

2.

opNew *op1 = new opNew;
opNew *op2 = new opNew;
opNew *op3 = new opNew;

则不同了。我们重载了new(*),是在上分配内存,在你手动销毁它之前是不会销毁的。所以test2的调用结束后,虽然出了局部变量(对象)op1(2,3)的作用域,但是因为内存没有被销毁,所以变量(对象)没有被销毁。因此也就不会自动调用析构函数了。

*当然了,系统默认的new也是在堆上分配内存的。

 

3.

opNew *op1 = new opNew;
opNew *op2 = new opNew;
opNew *op3 = new opNew;
delete op3;
delete op2;
delete op1;
因为我们调用了delete来销毁分配的内存,对象也被销毁了。所以会调用析构函数。

 

总之,我们平时说堆栈,其实是2个不同的概念。在写程序的时候,涉及到内存管理的时候,应该要区分这2个概念。