【问题标题】:why call operator new explicitly为什么要明确调用 operator new
【发布时间】:2010-11-10 14:40:57
【问题描述】:

我看到了这样的代码:

void *NewElts = operator new(NewCapacityInBytes);

随后显式匹配调用operator delete

为什么这样做而不是:

void *NewElts = new char[NewCapacityInBytes];

为什么要显式调用operator newoperator delete??

【问题讨论】:

标签: c++ memory-management new-operator


【解决方案1】:

像这样显式调用 operator new 会调用全局“原始”运算符 new。全局operator new 返回一个原始内存块,而不调用对象的构造函数或任何用户定义的new 重载。所以基本上,全局 operator new 类似于 C 中的 malloc

所以:

// Allocates space for a T, and calls T's constructor,
// or calls a user-defined overload of new.
//
T* v = new T;

// Allocates space for N instances of T, and calls T's 
// constructor on each, or calls a user-defined overload
// of new[]
//
T* v = new T[N];

// Simply returns a raw byte array of `sizeof(T)` bytes.
// No constructor is invoked.
//
void* v = ::operator new(sizeof(T));

【讨论】:

  • @zaharpopov:一个例子是实现一个内存池,在其中你分配一个大块一次,池的用户将调用在块内创建对象的函数,而不是使用new。根据分配模式,这可以提供比newdelete 更好的性能。
  • 哦。有趣的。我不知道C++的这个角。
  • 这个答案描述了operator new 的作用,但它没有解释为什么我们要使用operator new(N) 而不是new char[N]。毕竟这是个问题。
  • 我会说区别在于风格。 C++ 为您提供了很多方法来做同样的事情。
  • 实际上,我应该编辑答案以明确提及new T[N]
【解决方案2】:

如果你写:

T *p = new T;

这会分配足够的内存来保存 T,然后将 T 构造到其中。如果你写:

T *p = ::operator new(sizeof(T));

这会分配足够的内存来保存 T,但不会构造 T。您可能会看到这种情况之一是人们也在使用 Placement new:

T *p = ::operator new(sizeof(T)); // allocate memory for a T
new (p) T; // construct a T into the allocated memory
p->~T(); // destroy the T again
::operator delete(p); // deallocate the memory

【讨论】:

    【解决方案3】:

    如果你调用operator new(bytesize),那么你可以使用delete删除它,而如果你通过new char[bytesize]分配,那么你必须使用delete[]来匹配它,这是一个可憎的地方可能的。这很可能是使用它的根本原因。

    【讨论】:

    • 如果您通过全局operator new 分配,您可以使用全局operator delete 取消分配。但是 global operator delete 不会调用析构函数。所以如果你在调用全局operator new之后真的使用placement new构造了一个对象,那么仅仅全局operator delete是不足以销毁这个对象的。您还需要在释放内存之前显式调用析构函数。本质上,全局operator newoperator delete 都允许您将存储分配/释放和对象初始化/销毁解耦。
    • @Charles:他没有放置新的任何东西,并且该内存不需要破坏。作为纯粹分配内存的一种形式,operator new() 是最安全的选择,因为它不需要烦人的 delete[] 或不寻常的 free() 来解除分配。 @Steve: delete[] 是可憎的,因为它是不必要的。并不是说,当你使用 operator new 而不是 new[] 时,堆神奇地不需要存储块的大小或类似的东西。
    【解决方案4】:

    当您想要分配一块“原始”内存并且不想在该内存中构造任何东西时使用它。

    分配一块原始内存和“构造”一个​​字符数组之间几乎没有实际区别,但使用 operator new 可以向任何阅读重要代码的人清楚地表明你的意图。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-08-30
      • 2012-01-05
      • 1970-01-01
      • 2021-08-31
      • 1970-01-01
      • 1970-01-01
      • 2018-07-30
      相关资源
      最近更新 更多