如何使用malloc通过基类的指针为派生类的对象分配内存



例如,有一个链

class A
{
int a;
int b;
public:
A();
};
class B: public A
{
int c;
char b;
public:
B()
};

在创建派生类的对象的普通方式中,我们可以使用以下形式

A* ptr = new B()

如何使用malloc进行同样的操作?

Malloc返回一个指向原始分配内存的void*指针。只需在内存上使用一个新的放置操作符。

void* mem = malloc( sizeof(B) );
A* ptr = new(mem) B(); // builds object in location pointed by mem

新的放置不分配内存,它只是在给定的位置构造对象。

C方法:

A* ptr = (A*)malloc(sizeof(B));
*(B*)ptr = B();

C++的实现方式:

A* ptr = static_cast<A*>(malloc(sizeof(B)));
*static_cast<B*>(ptr) = B();

请注意,由于我们使用C++,因此必须强制转换malloc的返回值。

由于"语言混合",没有"ANSI方式"来回答这个问题。

new对类的实例进行两步构造。它分配堆内存,然后调用类的构造函数来初始化对象。

CCD_ 4转而仅处理存储器分配并且具有类似于CCD_ 5的签名。它不调用实例的构造函数。

CCD_ 6被称为放置新。它在完全初始化实例后返回ptr,调用相应的构造函数。

如果您需要使用标准堆以外的其他类型的内存,您可以覆盖类的操作符new和placement new。如果您需要将实例放置到线程本地存储、共享内存中,或者进行某种优化的数据结构,这将派上用场。此外,placement new有时用于系统编程,将对象的实例放在具有已知地址的某个寄存器集的顶部,以提供硬件接口的一些抽象。

所以,如果您想/需要对实例使用malloc(),那么您所要做的就是覆盖类的操作符new。并且可能不要忘记调用构造函数。

#include <new>
A *ManuallyConstructBInstance()
{
    B *pB = reinterpret_cast<B*>(operator new(sizeof(B)));
    if( nullptr != pB )
    {
         new(pB) B(); // manual call of constructor using placement new.
    }
    return pB; // optionally use static_cast<A*>() if you want to emphasize the upcast.
}

上面的代码示例显示了如果操作符new()被用作malloc()的替代,它看起来是什么样子,表明它只处理原始内存,而不倾向于类类型等。

要查看如何为类重载运算符new,请参见例如在这里

最新更新