为什么我更喜欢在堆上使用免费商店?

时间:2013-05-06 18:20:29

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

在Exceptional C ++中,Herb Sutter在第35项中写道:

  

首选使用免费商店(新/删除)。避免使用堆   (malloc的/自由)。

我为什么要这样?

如果某个实现选择使用new来实现malloc,则可能会产生开销,因此就性能而言,这看起来很糟糕。

1 个答案:

答案 0 :(得分:11)

C ++中的newdelete关键字通常以mallocfree的形式实现,但它们的目的是做不同的事情。

在C ++中,如果你说

new T(/* args */)

C ++将执行以下操作:

  • 尝试分配足够的内存来保存T类型的对象。
  • 失败时,尝试使用新处理程序释放空间,如果没有可用内存,最终会抛出std::bad_alloc对象。
  • 尝试在该内存块中构造类型为T的对象。
  • 如果构造T类型的对象引发异常,则自动释放内存。

如果您只使用malloc,则必须手动执行所有这些步骤,这非常非常非常。它可能看起来像这样:

T* memory = nullptr;
while (true) {
   memory = static_cast<T*>(malloc(sizeof(T)));
   if (memory != nullptr) break;

   std::get_new_handler()();  
}

try {
    new (memory) T(/* args */);
} catch (...) {
    free(memory);
    throw;
}

我在这里有一些其他的细微差别(比如调用operator new代替malloc,或处理零大小的请求等),但我希望这有助于解释{ {1}}和new不同。

那么为什么要使用malloc而不是new?嗯,有几个原因:

  • 它更安全。使用malloc您可以忘记检查空指针的返回类型,或者您可以请求错误的存储空间量,或者您可以忘记在对象上调用构造函数,否则如果构造函数抛出异常等,你可能会忘记释放内存。

  • 它更加类型安全。 malloc返回malloc,它只是指向内存块的指针。使用void*,您必须将指针强制转换为正确的类型,这可能会在以后引入错误。

  • 它允许自定义。某些类型重载malloc以异常方式请求内存,例如来自池化分配器或可能更快的某些内存块,或者使用优化使用模式的自定义分配器。鉴于此,您可以通过定义operator newT自动自定义为operator new类型的对象动态分配内存的所有时间。如果您使用operator delete,则必须在整个程序中追踪所有内存分配站点。

也就是说,malloc有一些优点。如果您确定要分配的对象是简单的对象(例如只保存数据的基元或结构),则使用malloc可能会稍快一些。 malloc还允许您使用mallocrealloc不会。但老实说,在这样的情况下,你可能最好只使用freestd::vector,因为它们更安全,更容易调试,并且具有良好的编译器支持可能会被积极地优化。 / p>

希望这有帮助!