如果我已经重载了 "operator new",那么如何调用原始的 "operator new"?

32
假设我需要重载全局::operator new() 以便与每个分配的对象一起存储额外数据。基本上它的工作方式如下:
  • 对于每次调用全局::operator new(),它将获取传递的对象大小并添加额外数据的大小
  • 它将分配一个内存块,该块的大小在前一步中推导出来
  • 它将偏移指针到未被额外数据占用的块的部分,并将该偏移值返回给调用者

::operator delete()将执行相反的操作-移动指针、访问额外数据、释放内存。

现在问题是我如何分配内存?当然我可以调用malloc()或一些特定于平台的函数(通常是这样做的)。但是通常情况下,当我需要在C++中分配原始内存时,我会调用::operator new()。我能否从我的重载的全局::operator new()内部调用原始的::operator new()来执行内存分配?


8
你的意思是过载还是替代?如果是过载,只需使用正确的参数集调用原始操作符new即可。如果是替代,那么不行,但我相信这就是为什么malloc保证在其实现中不使用operator new(即当operator new被替换时不会出现意外循环)所以你应该使用malloc。 - CB Bailey
2
@CharlesBailey 你把你的答案写成了评论!真丢人! - lmat - Reinstate Monica
1个回答

23
你无法访问它们,因为它实际上不是重载,而是替换。当你定义自己的::operator new时,旧的被取代了。就是这样。
基本上,你需要从自定义的::operator new中调用malloc。不仅如此,还需要按照18.4.1.1/4中的说明正确处理错误:
默认行为:
- 执行循环: 在循环内部,函数首先尝试分配所请求的存储空间。是否涉及调用标准 C 库函数 malloc 是未指定的。 - 如果尝试成功,则返回指向已分配存储空间的指针。否则,如果 set_new_handler() 的最后一个参数是 null 指针,则抛出 bad_alloc。 - 否则,函数调用当前的 new_handler(18.4.2.2)。如果被调用的函数返回,则重复该循环。 - 当尝试分配所需存储空间成功或被调用的 new_handler 函数没有返回时,循环终止。

1
不要忘记将 operator delete 也替换为 free() - wilhelmtell
我相信Scott Meyers在他的《Effective C++》系列的某本书中详细讨论了这个问题。似乎是第二版的第8条款和第三版的第8章节。 - wilhelmtell
@Potatoswatter:他不能使用malloc()为他的类和额外数据分配内存,然后调用“放置new”在这个内存中实例化类对象吗?既然他只是替换了常规版本的new,默认的placement-new不会被调用吗? - Praetorian
1
@Sharptooth:你可以将所有内容放在try-catch块中,清理已分配的内存并重新抛出异常。 - Praetorian
@Charles Bailey:是的,当然可以,但只有在我使用new语句时才可以。用户Praetorian似乎建议我先分配内存,然后通过放置new在原地调用构造函数。这种情况下,C ++不会处理内存释放。 - sharptooth
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接