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

qdi*_*dii 4 c++ memory-management new-operator

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

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

我为什么要?

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

tem*_*def 11

C++中的newdelete关键字通常是根据malloc和实现的free,但它们的设计目的是做不同的事情.

在C++中,如果你说

new T(/* args */)
Run Code Online (Sandbox Code Playgroud)

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;
}
Run Code Online (Sandbox Code Playgroud)

这里有一些其他的细微差别我已经掩盖了(比如打电话operator new代替malloc,或处理零大小的请求等),但我希望这有助于解释如何newmalloc不同.

那你为什么要new用完malloc呢?嗯,有几个原因:

  • 它更安全. 有了malloc你可以忘记检查返回类型为一个空指针,或者你可以要求的存储空间量错了,或者你可以忘记调用对象的构造函数,或者你可以忘记释放内存,如果构造函数抛出异常等

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

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

也就是说,有一些优点malloc.如果你肯定知道你正在分配对象是简单的对象(比如只保存数据的基元或结构),那么使用起来可能会稍快一些malloc. malloc也让你使用realloc,free但没有.但老实说,你可能最好只使用std::vectorstd::array在这种情况下,因为它们更安全,更容易调试,并且具有良好的编译器支持可能会被积极优化.

希望这可以帮助!