C++重载内存分配时需要注意的地方


一、测试代码

#include <stdio.h>
#include <malloc.h>
#include <new>

//#define VF
//#define FLAG

class MemObj
{
public:
    #ifdef VF
    virtual ~MemObj(void) {}
    #endif // VF

    static void* operator new(size_t stSize)
    {
        printf("operator new(size_t) %d\n", stSize);
        return malloc(stSize);
    }

    #ifdef FLAG
    static void operator delete(void* pMemory)
    {
        printf("operator delete(void*)\n");
        free(pMemory);
    }
    #endif

    static void operator delete(void* pMemory, size_t stSize)
    {
        printf("operator delete(void*, size_t) %d\n", stSize);
        free(pMemory);
    }
};

class Test : public MemObj
{
private:
    int m_nValue;
};

int main(int argc, char** argv)
{
    MemObj* pObj = new MemObj();
    delete pObj;

    Test* pTest = new Test();
    delete pTest;

    pObj = new Test();
    delete pObj;

    return 0;
}

二、测试

通过控制宏VF和宏FLAG的定义与否来查看各个情况下代码运行的结果。

测试1:不定义宏VF和FLAG

operator new(size_t) 1
operator delete(void*, size_t) 1
operator new(size_t) 4
operator delete(void*, size_t) 1
operator new(size_t) 4
operator delete(void*, size_t) 1

测试2:定义宏FLAG但不定义宏VF

operator new(size_t) 1
operator delete(void*)
operator new(size_t) 4
operator delete(void*)
operator new(size_t) 4
operator delete(void*)

测试3:定义宏VF但不定义宏FLAG

operator new(size_t) 4
operator delete(void*, size_t) 4
operator new(size_t) 8
operator delete(void*, size_t) 8
operator new(size_t) 8
operator delete(void*, size_t) 8

测试4:同时定义宏VF和FLAG

operator new(size_t) 4
operator delete(void*)
operator new(size_t) 8
operator delete(void*)
operator new(size_t) 8
operator delete(void*)

三、结果分析

1. 对比测试1和测试2

重载了operator new(size_t stSize)后,在删除的时候:

  1. 如果没有定义 void operator delete(void* pMemory) ,那么会调用 void operator delete(void* pMemory, size_t stSize)
  2. 如果定义了 void operator delete(void* pMemory) ,不管是否定义 void operator delete(void* pMemory, size_t stSize) 都会调用 void operator delete(void* pMemory)

结论:
重载 operator new(size_t) 后,如果同时重载了 operator delete(void*) ,删除时候会调用 operator delete(void*) ,否则才会调用 operator delete(void*, size_t)

2. 对比测试1和测试3

如果不将基类的析构函数定义为虚析构函数,会有内存泄漏。


文章作者: Kiba Amor
版权声明: 本博客所有文章除特別声明外,均采用 CC BY-NC-ND 4.0 许可协议。转载请注明来源 Kiba Amor !
  目录