运算符"delete this"究竟是怎么做的呢?

How the operator "delete this" do exactly?

我刚刚测试了有关 "delete this" 的运算符。使用 handle 系统调用 "new/delete" 将丢失一个覆盖删除函数调用。

句柄函数如下:

inline void* operator new(size_t size)
{
    void* p = ::malloc( size );
    fprintf( stderr, "new size %ld: %p\n", size, p );
    return p; 
}

inline void* operator new[]( size_t size )
{
    void* p = ::malloc( size );
    fprintf( stderr, "new size[] %ld: %p\n", size, p );
    return p; 
}

inline void  operator delete(void* p)    
{
    fprintf( stderr, "delete: %p\n", p );
    ::free(p); 
}

inline void  operator delete[](void* p)  
{
    fprintf( stderr, "delete []: %p\n", p );
    ::free(p); 
}

并测试 class:

class A
{
    public:
        A() : a(NULL)
        {
            printf( "A construct\n" );
            a = new int[100];
        }

        ~A()
        {
            printf( "A destruct \n" );
            freeA();
        }

        void freeA()
        {
            if ( a ) { delete [] a; a = NULL; }
        }

        void release()
        {
            delete this;
        }

    private:
        int*    a;
};

当我打电话时

A* a = new A();
a->release();

结果是:

new size 8: 0x5642fc1c4e70
A construct
new size[] 400: 0x5642fc1c52a0
A destruct 
delete []: 0x5642fc1c52a0

缺少关于 A(0x5642fc1c4e70) 的删除调用,为什么?

我刚发现问题:使用内联,运算符 delete(void* p) 根本无法调用。但是 delete[](void* p) 可以。 现在我将关闭它。

https://timsong-cpp.github.io/cppwp/replacement.functions#3

The program's definitions are used instead of the default versions supplied by the implementation ([support.dynamic]). Such replacement occurs prior to program startup ([basic.def.odr], [basic.start]). The program's declarations shall not be specified as inline. No diagnostic is required.

这是规则。不允许内联。这就是您缺少一个删除的原因,它在没有内联说明符的情况下也能工作。

我运行将你的代码设置在c++14以下,你的delete运算符可以被正确调用。

https://onlinegdb.com/S1zAgzXbB

但是,运行宁超过版本 c++14(包括 c++14),然后需要将代码从 inline void operator delete(void* p) 更改为 inline void operator delete(void* p,std::size_t sz) 或删除 inline 关键字。那么您的代码将 运行 正确

https://onlinegdb.com/BJ3hMz7WH

希望对你有所帮助

既然你已经定义了一个析构函数,那么就不需要定义释放函数了。直接在实例的指针上使用 delete

而不是

A* a = new A();
a->release();

你会

A* a = new A();
delete a;

删除 a 将调用 ~A() 析构函数