4

在 Exceptional C++ 中,Herb Sutter 在 Item 35 中作为指导写道:

更喜欢使用免费商店(新建/删除)。避免使用堆(malloc/free)。

我为什么要?

如果实现选择new使用 using来实现malloc,则可能会产生开销,因此就性能而言,这看起来像是一个糟糕的建议。

4

1 回答 1

11

C++ 中的newanddelete关键字通常是用mallocand来实现的free,但是它们被设计用来做不同的事情。

在 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,或处理零大小的请求等),但我希望这有助于解释它们newmalloc不同之处。

那么为什么要使用newovermalloc呢?嗯,有几个原因:

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

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

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

也就是说,有一些优势malloc。如果您确定要分配的对象是普通对象(例如仅保存数据的基元或结构),则使用malloc. malloc也可以让你使用reallocfree但不能。std::vector但老实说,在这种情况下你可能会更好std::array,因为它们更安全,更容易调试,并且具有良好的编译器支持可能会被积极优化。

希望这可以帮助!

于 2013-05-06T18:31:35.627 回答