当我们超载new运算符时,是否有必要重载放置new运算符?

bjs*_*123 8 c++

我有下面的代码

class Test 
{
public:
    Test(){}
    Test(int i) {}

  void* operator new (size_t size)
  {
      void *p = malloc(size);
      return p;
  }
  //void* operator new (size_t size, Test *p)
  //{
     // return p;
  //}
};

int main() { 
   Test *p = new Test;
   int i = 10;
   new(p) Test(i);
}
Run Code Online (Sandbox Code Playgroud)

上面的代码片段不能在visual studio中编译,除非我取消注释重载的放置新操作符函数.如果我注释掉正常重载的新内容,那么它也能正常工作.重载正常的新运算符时是否重载了新的必需项(如果需要为该类使用新的位置)

此处未显示展示位置删除相关代码.

Pot*_*ter 3

通常不会,因为它不经常使用。但这可能是必要的,因为当您operator new在类中重载时,它会隐藏全局::operator new.

因此,如果您想在该类的对象上使用placement new,请执行以下操作:否则不要。新的也同样如此nothrow

如果您刚刚更改了分配方案,并且您对某个地方有人在您背后使用新的放置感到惊讶,那么在应用此创可贴之前可能需要进行调查。

如果该类在标准库容器内使用,而不是直接与 一起使用new,则自定义分配方案应由 Allocator 类定义,而不是重载。默认分配器std::allocator不考虑成员operator new重载,而是绕过它们。见下文。


免责声明:类范围operator new重载主要用于调试,即使如此,获得可靠且有意义的语义也很困难。谨防:

  • 你还需要超载operator delete。(本问题的示例中未完成。)

  • 重载将被限定语法绕过::new T。您无法阻止此类绕过。这就是分配事物的方式std::allocator<T>。你可以专门std::allocator针对你的类型,但这已经是进入兔子洞的方式了。

  • 对于::operator new任何库引入的每个重载,包括规范放置 new from <new>,您必须考虑它是否适用于您的类,并决定是否添加重载,或者以其他方式应对不合格new表达式的失败。

  • ::operator new对于您在班级中采用的每个成员,您必须提供operator delete具有正确语义的相应成员位置。如果构造函数因异常退出,则调用此函数。如果没有它,只有在非常特定的情况下,在可能资源受限的池中,才会导致内存泄漏。

总之,成员operator new是防御性编码的对立面。