Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/angularjs/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 当我们重载新操作符时,是否有必要重载新操作符?_C++ - Fatal编程技术网

C++ 当我们重载新操作符时,是否有必要重载新操作符?

C++ 当我们重载新操作符时,是否有必要重载新操作符?,c++,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() {

我有下面一段代码

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);
}
除非我取消注释重载的placement new operator函数,否则上述代码不会在VisualStudio中编译。 如果我注释掉正常重载的new,在这种情况下,它也可以正常工作。 重载普通新运算符时是否必须重载placement new(如果该类需要使用placement new)


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

通常不显示,因为它不经常使用。但这可能是必要的,因为在类中重载
操作符new
时,它会隐藏全局
::操作符new
的所有重载

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

<> P>如果你刚刚改变了分配方案,你会惊奇地发现某处有人在你背后使用新的布局,这可能是在应用这个创可贴之前要进行的调查。

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


免责声明:class scope
operator new
重载主要用于调试,即使如此,也很难获得可靠的有意义语义。注意:

  • 您还需要重载
    操作员删除
    。(本问题示例中未进行此操作。)

  • 重载将被限定语法
    ::new T
    绕过。你无法阻止这种绕过。这就是
    std::allocator
    分配事物的方式。您可以为您的类型专门化
    std::allocator
    ,但这已经是兔子洞的一部分了

  • 对于每个<代码>:由任何库引入的运算符new < /COD>重载,包括从<代码> <代码>中的规范放置,您必须考虑它是否适用于您的类并决定是否添加重载,否则将与不合格代码<新> <代码>表达式进行争用。

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


总之,成员
运算符new
是防御编码的对立面。

对于类,默认情况下不存在放置新运算符,因此当您调用
new(p)Test(i) C++编译器找不到上面例子中注释函数的定义。如果您取消对类的placement运算符new的注释,并注释掉“normal”运算符,那么将使用默认的“normal”新运算符,并且您的代码将被编译。

std::_构造的实现使用全局placement new。因此,对STL兼容性的关注不应该成为关注的焦点。但担心破坏现有的代码,这可能是书面的

新的((void*)p)事物

而不是

::新的((void*)p)事物


这当然是一个正确的观点。

实际上,无论何时出于这个原因实施自定义
new
时,实施placement和nothrow
new
都是一个好主意。如果不能提供new和delete(不要忘记数组形式)的六个版本,您可能会破坏现有代码。代码中不经常使用placement
new
,但STL容器经常使用它来将内存分配与对象构造分开。@Philip:那是个危险信号,由于
std::allocator
::operator new
获取内存。在这种情况下,解决方案是实现一个自定义分配器,而不是启用标准分配器。@Potato:不,这不是问题所在。问题是,如果
std::vector
需要放置
new
来构建
MyClass
,那么
MyClass
最好提供一个。
vector
从哪里获得内存并不重要。@Philip:如果
vector
从错误的地方获得内存,那就是一个bug。实现自定义分配器也可能需要新的位置(无论如何,根据法律的规定),因此它可能会以某种方式返回。也许我不应该急于下结论,但这绝对是个问题。