Malloc vs New for Primitives

Malloc vs New for Primitives

我了解在 C++ 中使用 new 而不是 malloc 的好处。但是对于原始数据类型(非数组)-intfloat等特定情况,使用malloc是否比new更快?

虽然,即使对于基元,也始终建议使用 new,如果我们正在分配一个数组,以便我们可以使用 delete[]

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

请指教

使用 new 总是更好。如果您使用 malloc,您仍然需要手动检查是否分配了 space。

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

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

建议是:

  • 问问自己:"do I need dynamic memory allocation?"。很多时候你可能不需要它 - 更喜欢 values 而不是指针并尝试使用堆栈。

  • 如果您确实需要动态内存分配,请问问自己 "who will own the allocated memory/object?"

    • 如果你只需要一个所有者(很有可能),你应该 使用 std::unique_ptr。它是一个零成本的抽象 new/delete。 (可以指定不同的释放器 。)

    • 如果你需要共享所有权,你应该使用std::shared_ptr。这不是零成本抽象,因为它使用原子操作和额外的"control block"来跟踪所有所有者。


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

std::arraystd::vector 应该覆盖你的 99% "array needs".


还有一件重要的事情:标准库提供了std::make_unique and std::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. ...

    如果 g() 抛出,则 int 泄漏。

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

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

"should I use new or malloc"的答案是单一职责规则

资源管理应该由一个以资源管理为唯一目的的类型来完成。
那些类已经存在,比如unique_ptrvector

直接使用 mallocnew 是大错。

当您与使用纯 C 指定的 API 交互时,仍然需要在 C++ 中使用 mallocfree,因为它 不是 保证可以安全地使用 free 来释放使用 operator new 分配的内存(这最终是所有托管内存 类 使用的内存),也不会使用 operator delete 以释放使用 malloc.

分配的内存

一个典型的例子是POSIX getline (not to be confused with std::getline):它接受一个指向char *变量的指针;该变量必须指向分配有 malloc 的内存块(或者它可以为 NULL,在这种情况下 getline 将为您调用 malloc);完成调用 getline 后,您应该对该变量调用 free

类似地,如果你正在编写一个库,在内部使用 C++ 但为你的外部调用者定义一个 extern "C" API 是有意义的,因为这会给你更好的二进制接口稳定性和交叉- 语言互操作性。如果你 return 堆分配 POD 对象给你的调用者,你可能想让他们用 free 释放这些对象;他们不一定使用 delete,并且在不需要析构函数类型的操作时让他们调用 YourLibraryFree 是不符合人体工程学的。

实现 可调整大小的容器对象时,仍然需要使用 malloc,因为 [=13= 没有 realloc 的等价物].

但正如其他答案所说,当您没有这种接口约束时,请改用其中一种托管内存 类。

已经给出了正确的正确答案:使用 malloc()/free() when interacting with C interfaces only.
我不会重复这些细节,我会回答性能问题。

事实是,malloc()new 的性能可以而且确实不同。当您使用 new 执行分配时,通常会通过调用全局 operator new() 函数来分配内存,这与 malloc() 不同。通过调用 malloc() 来实现 operator new() 很简单,但不一定要这样做。

事实上,我见过一个系统,其中调用 malloc()operator new() 的性能比 operator new() 的标准实现高出大约 100 CPU 每次通话的周期数。这绝对是一个可衡量的差异,并且清楚地表明标准实现与 malloc().

有很大不同。

所以,如果您担心性能,可以做三件事:

  1. 衡量你的表现。

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

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

gains/losses 可能重要也可能不重要。