【问题标题】:Override delete operator覆盖删除运算符
【发布时间】:2013-02-11 19:54:06
【问题描述】:

我想覆盖我班级中的删除运算符。这是我正在尝试做的,但没有成功。

class Complex{              
    void *operator new(size_t s);
    void operator delete(void *ptr);
};

void Complex::operator delete(void *ptr){
    delete ptr;
}

我得到错误:

删除 void* 是未定义的

【问题讨论】:

  • 你可能想要::delete ptr;
  • 方法签名看起来不对,new 没有size_t 参数(只有new[] 有),但delete 确实 有一个size_t 参数。
  • 您不能覆盖delete 运算符;这是一个语言关键字。您正在做的是覆盖operator delete,这是一个由delete 运算符调用的函数。这听起来像是一个文字游戏,但这是一个重要的区别。
  • delete 不应将 size_t 作为参数。因为我想这样写: Complex c = new Complex();删除 c;
  • operator delete 必须撤消 operator new 所做的任何事情。你能告诉我们operator new吗?

标签: c++ oop new-operator


【解决方案1】:

如错误消息所示,您不能 deletevoid*。试试这个:

// See http://www.informit.com/guides/content.aspx?g=cplusplus&seqNum=40

#include <new> // for size_t

class Complex
{
public:
 Complex() {}
 ~Complex() {}
 static void* operator new (size_t size) {
  return new char[size];
 }
 static void operator delete (void *p) {
  return delete[] static_cast<char*>(p);
 }
};

int main () {
  Complex *p = new Complex;
  delete p;
}

【讨论】:

    【解决方案2】:

    您的声明是正确的。问题在于实现operator delete 的代码:它使用关键字delete 而不是调用全局operator delete。像这样写:

    void Complex::operator delete(void *ptr) {
        ::operator delete(ptr);
    }
    

    假设您的operator new 使用了全局operator new

    【讨论】:

    • 所以,在新方法中写下:return (::operator new(s));
    • @AntonioKumar - 是的,静态成员函数可以写成这样调用全局operator new。当然,这引发了它为什么存在的问题,因为它只是做了编译器在它不在时会做的事情。
    【解决方案3】:

    通过delete删除很奇怪,但是删除一个void*就是UB。

    另外,size_t 不是内置类型:它在 &lt;cstddef&gt; 中定义。

    这样就好了:

    #include <cstddef>
    
    class Complex
    {              
        void *operator new(size_t s);
        void operator delete(void *ptr);
    };
    
    void* Complex::operator new(size_t s)
    { return new char[s]; } //allocate a buffer of s bytes
    
    void Complex::operator delete(void *ptr)
    { delete[] static_cast<char*>(ptr); } //deallocate the buffer
    

    实际上,我们在 new / delete 中连贯地分配/取消分配适当大小的缓冲区。

    new 中,我们要求系统给我们我们需要的字节。我使用了char[s],因为char 是内存的单位size_t 度量:sizeof(char) == 1 的定义。

    delete 中,我们必须将ptr 标识的字节返回给系统。 由于我们将它们分配为char[],因此我们必须将它们删除为char[],因此使用delete[] 并转换为char*

    【讨论】:

    • 那么,我可以知道这两行发生了什么吗?
    • 在这里使用static_cast,而不是reinterpret_cast
    • @EmilioGaravaglia:使用static_cast 撤消隐式转换(char* 隐式转换为void*),reinterpret_cast 太强了。您没有重新解释任何内容,只是正确地撤消了隐式转换。