Malloc与Primitives的新作

时间:2017-06-16 11:37:36

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

我理解在C ++中使用newmalloc的好处。但对于特定情况,例如原始数据类型(非数组) - intfloat等,使用malloc比使用new更快吗?

尽管我们总是建议使用new甚至是基元,如果我们分配一个数组以便我们可以使用delete[]

但是对于非数组分配,我认为int不会有任何构造函数调用吗?因为,new运算符分配内存,检查它是否已分配,然后调用构造函数。但是对于原始非数组堆分配,使用malloc比使用new更好吗?

请告知。

5 个答案:

答案 0 :(得分:83)

永远不要在C ++中使用malloc。除非您正在实现低级内存管理原语,否则切勿使用new

建议是:

  • 问问自己:“我需要动态内存分配吗?”。很多时候你可能不需要它 - 喜欢指针并尝试使用堆栈。

  • 如果您确实需要动态内存分配,请问自己“谁将拥有已分配的内存/对象?”

    • 如果您只需要一个拥有者(非常可能),您应该这样做 使用std::unique_ptr。这是一个零成本的抽象 new / delete。 (可以指定不同的deallocator 。)

    • 如果您需要共享所有权,则应使用std::shared_ptr。这是零成本抽象,因为它使用原子操作和额外的“控制块”来跟踪所有所有者。

如果您特别处理数组,标准库提供了两个功能强大且安全的抽象,不需要任何手动内存管理:

std::arraystd::vector应涵盖99%的“阵列需求”。

更重要的一点是:标准库提供std::make_uniquestd::make_shared始终用于创建智能指针实例。有几个很好的理由:

  • 更短 - 无需重复T (例如std::unique_ptr<T>{new T},无需使用new

  • 更安全的例外情况。它们可以防止由于函数调用中缺乏明确定义的评估顺序而导致的潜在内存泄漏。例如。

    f(std::shared_ptr<int>(new int(42)), g())
    

    可按此顺序进行评估:

    1. new int(42)
    2. g()
    3. ...
    4. 如果g()抛出,int就会泄露。

    5. 更高效(就运行时速度而言)。这仅适用于std::make_shared - 使用它而不是std::shared_ptr直接允许实现为对象和控制块执行单个分配。

您可以在this question中找到更多信息。

答案 1 :(得分:26)

当您与使用普通C指定的API进行交互时,仍然需要在C ++中使用mallocfree,因为它保证是安全的使用free释放分配了operator new的内存(最终是所有托管内存类使用的内存),也不使用operator delete来释放分配了malloc的内存。< / p>

一个典型的例子是POSIX getline(不要与std::getline混淆):它需要一个指向char *变量的指针;该变量必须指向使用malloc分配的内存块(或者它可以为NULL,在这种情况下getline将为您调用malloc;当您完成呼叫getline后,您应该在该变量上调用free

同样,如果您正在编写库,那么在内部使用C ++是有意义的,但为外部调用者定义extern "C" API,因为这可以提供更好的二进制接口稳定性和跨语言互操作性。如果将堆分配的POD对象返回给调用者,您可能希望让它们使用free释放这些对象;他们不一定能使用delete,并且当没有需要析构函数类型的操作时让它们调用YourLibraryFree是不符合人体工程学的。

实现可调整大小的容器对象时,仍然需要使用malloc,因为realloc没有等效operator new

但正如其他答案所说,当你没有这种界面约束时,请使用其中一个托管内存类。

答案 2 :(得分:8)

使用new总是更好。如果您使用malloc,则仍需要手动检查是否已分配空间。

在现代c ++中,您可以使用智能指针。使用make_uniquemake_shared,您永远不会明确地调用newstd::unique_ptr不大于底层指针,使用它的开销很小。

答案 3 :(得分:6)

&#34;的回答我应该使用new还是malloc&#34; 单一责任规则

资源管理应该以一种唯一目的来完成 这些类已经存在,例如unique_ptrvector等。

直接使用mallocnew是罪恶的主要罪行。

答案 4 :(得分:2)

zwol's answer已经提供了正确的正确答案:与C接口交互时使用malloc() / free()
我不打算重复这些细节,我将回答性能问题。

事实是,malloc()new的表现可以并且确实有所不同。当您使用new执行分配时,通常会通过调用全局operator new()函数来分配内存,该函数与malloc()不同。通过调用operator new()来实现malloc()是微不足道的,但这不一定完成。

事实上,我已经看到一个系统,其中调用operator new()的{​​{1}}优于malloc()的标准实现,每次调用大约100个CPU周期。这绝对是一个可衡量的差异,并清楚地表明标准实现与operator new()有很大不同。

所以,如果你担心表现,有三件事要做:

  1. 衡量您的表现。

  2. 为全局malloc()函数及其朋友编写替换实现。

  3. 衡量您的表现并进行比较。

  4. 收益/损失可能会也可能不会很大。