具有自己内存分配的课程设计

Design of classes with own memory allocation

本文关键字:分配 自己 内存      更新时间:2023-10-16

我在设计将使用自己的内存分配的适当类时遇到了一些麻烦。考虑一下:

class IAbstract { ... };
class CConcrete : public IAbstract { ... };

我想做这样的事情:

IAbstract *ptr = new CConcrete();
delete ptr;

问题是,我希望cconcrete的"新"使用内存分配器。另外,我希望"删除"使用适当的Deallocator。但是,新的和删除是静态函数,因此在上面的示例中删除不会调用cconcrete的删除(如果删除是虚拟的,则应该这样做)。

解决此问题的一种方法是使这样的事情:

class IAbstract {
public:
   virtual Delete(void* ptr)=0;
   void operator delete(void* ptr) {
      ((IAbstract*)(ptr))->Delete(ptr);
   }
}; 

和在派生类中删除删除。但是,该解决方案非常丑陋,尤其是将PTR投射到iabtract*。

有什么更好的方法吗?

您是否尝试过?安置新/删除

精确地知道代码出了什么问题是很困难的。我能做的最好的就是向您展示一个工作程序。

考虑此程序:

#include <iostream>
#define X() (std::cout << __PRETTY_FUNCTION__ << "n")
class IAbstract {
public:
  virtual ~IAbstract() { X(); }
};
class CConcrete : public IAbstract {
public:
  void* operator new(size_t sz) {
    X();
    return ::operator new(sz); // or however you allocate memory
  }
  void operator delete(void* p) {
    X();
    ::operator delete(p); // or however you de-allocate memory
  }
  ~CConcrete() { X(); }
};
int main () {
  IAbstract *ptr = new CConcrete();
  delete ptr;
}

我的计算机上的输出是:

static void* CConcrete::operator new(size_t)
virtual CConcrete::~CConcrete()
virtual IAbstract::~IAbstract()
static void CConcrete::operator delete(void*)

请注意,执行delete ptr时,delete正确调用虚拟破坏者正确的operator delete()

注意:由于使用__PRETTY_FUNCTION__

,这需要G

第一个有趣的事情是,您无法施放无效指针来调用任何成员函数。从技术上讲,它是编译的,但是在之后,操作员删除被称为对象(或对象层次结构)被破坏(通过调用destructor(s))。换句话说 - 您正在做的是UB,因为您正在尝试访问被破坏的班级的VT。

另一件事是,只要您的破坏者是虚拟的,可以在类上调用适当的删除操作员。因此,除此之外,无需使用额外的VTAble资源来重新发明自己的机制。我认为以下方法是您要寻找的:

#include <new>
#include <cstdio>
#include <cstdlib>
class Base {
  public:
    Base() { }
    virtual ~Base() { printf("Base::~Base()n"); }
};
class Derived : public Base {
    char data[256];
  public:
    Derived() {}
    virtual ~Derived() { printf("Derived::~Derived()n"); }
    void *operator new(size_t size)
    {
        void *p = malloc(size);
        printf("Allocated %lu bytes @ %pn", size, p);
        return p;
    }
    void operator delete(void *ptr)
    {
        printf("Freeing %pn", ptr);
        free(ptr);
    }
};
int main()
{
    Base *b = new Base();
    delete b;
    b = new Derived();
    delete b;
}

,但不要忘记,一旦您删除虚拟驱动器,就不会删除超载的操作员。