void* in malloc vs operator new

void* in malloc vs operator new

本文关键字:operator new vs malloc in void      更新时间:2023-10-16

今天我为我的代码编写了一个小型内存档案器,并且第一次重载了operator new。在这样做的过程中,我认为语法是void* operator new(size_t sz)。这确实与malloc非常相似,其中有void* malloc(size_t sz)

这让我开始思考,因为当你使用malloc时,你需要显式地将指针投射回你的数据类型,而对于new,你不需要这样做。编译器如何为new确定正确的数据类型?为什么返回void *T* operator new(size_t sz)不是更直观吗?

operator new函数不返回T*,因为返回的值不指向T,而只是指向任意垃圾。直到调用构造函数,才有了指向类实例的指针。

C++分离内存分配和对象构造。分配函数(即operator new())将void *返回到某个内存,并且new运算符在该内存中构造对象。如果你愿意的话,new操作符将内存"转换"为对象,而placement-new表达式有点像"cast":

void * addr = ::operator new(sizeof(Foo));    // memory
Foo * p = ::new (addr) Foo(1, true, 'a');     // object (note: no cast!)
p->~Foo();                                    // it's almost over
::operator delete(addr);                      // now it's over!

new的默认非放置表单一次性执行分配和构造。这在道德上相当于这个例子的前半部分。但是,分配和建设仍然是两个截然不同的概念。

operator new和新运算符之间存在差异。后者创建给定类型的对象,前者只是分配内存。新运算符为正在创建的类型调用operator new,或者,如果没有为所需类型定义版本,则使用全局operator new。不能从operator new函数返回T*,因为它将指向尚未创建的对象。只有在构造函数运行后(以及任何内务管理,如vtable创建、RTTI信息等),才会创建对象。

不要忘记,您可以为任何类重写operator new并更改它的行为——它实际上不需要分配任何内存,只需要返回一个指向某些内存的指针。例如,该内存可以来自预先分配的块。

operator newnew运算符的一个用户可重写的运行时支持功能,它只提供分配适当对齐和大小的内存块的服务。此函数本身不是new运算符;当您重写此函数时,并不是在重写new运算符本身,而只是替换分配服务。new运算符可以被认为是一个语法糖,它编译成对其助手operator new的调用,以获取内存,如果需要,还可以调用构造函数来初始化内存。