例如,有一个链
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,请参见例如在这里