Malloc vs New for Primitives
Malloc vs New for Primitives
我了解在 C++ 中使用 new
而不是 malloc
的好处。但是对于原始数据类型(非数组)-int
、float
等特定情况,使用malloc
是否比new
更快?
虽然,即使对于基元,也始终建议使用 new
,如果我们正在分配一个数组,以便我们可以使用 delete[]
。
但是对于非数组分配,我认为int
不会有任何构造函数调用?因为,new
运算符分配内存,检查它是否已分配,然后调用构造函数。但仅对于原语非数组堆分配,使用 malloc
是否比 new
更好?
请指教
使用 new
总是更好。如果您使用 malloc
,您仍然需要手动检查是否分配了 space。
在现代 C++ 中,您可以使用智能指针。使用 make_unique
和 make_shared
你永远不会显式地调用 new
。 std::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::array<T, N>
: N
类型元素的固定数组 T
.
类型元素的可调整大小数组
std::array
和 std::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())
可以按以下顺序计算:
new int(42)
g()
- ...
如果 g()
抛出,则 int
泄漏。
更高效(就运行-时间速度而言)。这仅适用于 std::make_shared
- 使用它而不是 std::shared_ptr
直接允许实现为对象和控制块执行单个分配。
您可以在 this question 中找到更多信息。
"should I use new
or malloc
"的答案是单一职责规则。
资源管理应该由一个以资源管理为唯一目的的类型来完成。
那些类已经存在,比如unique_ptr
、vector
等
直接使用 malloc
或 new
是大错。
当您与使用纯 C 指定的 API 交互时,仍然需要在 C++ 中使用 malloc
和 free
,因为它 不是 保证可以安全地使用 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()
.
有很大不同。
所以,如果您担心性能,可以做三件事:
衡量你的表现。
为全局 operator new()
函数及其朋友编写替换实现。
衡量你的表现并进行比较。
gains/losses 可能重要也可能不重要。
我了解在 C++ 中使用 new
而不是 malloc
的好处。但是对于原始数据类型(非数组)-int
、float
等特定情况,使用malloc
是否比new
更快?
虽然,即使对于基元,也始终建议使用 new
,如果我们正在分配一个数组,以便我们可以使用 delete[]
。
但是对于非数组分配,我认为int
不会有任何构造函数调用?因为,new
运算符分配内存,检查它是否已分配,然后调用构造函数。但仅对于原语非数组堆分配,使用 malloc
是否比 new
更好?
请指教
使用 new
总是更好。如果您使用 malloc
,您仍然需要手动检查是否分配了 space。
在现代 C++ 中,您可以使用智能指针。使用 make_unique
和 make_shared
你永远不会显式地调用 new
。 std::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::array<T, N>
:N
类型元素的固定数组T
.- 类型元素的可调整大小数组
std::array
和 std::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())
可以按以下顺序计算:
new int(42)
g()
- ...
如果
g()
抛出,则int
泄漏。更高效(就运行-时间速度而言)。这仅适用于
std::make_shared
- 使用它而不是std::shared_ptr
直接允许实现为对象和控制块执行单个分配。
您可以在 this question 中找到更多信息。
"should I use new
or malloc
"的答案是单一职责规则。
资源管理应该由一个以资源管理为唯一目的的类型来完成。
那些类已经存在,比如unique_ptr
、vector
等
直接使用 malloc
或 new
是大错。
当您与使用纯 C 指定的 API 交互时,仍然需要在 C++ 中使用 malloc
和 free
,因为它 不是 保证可以安全地使用 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()
.
所以,如果您担心性能,可以做三件事:
衡量你的表现。
为全局
operator new()
函数及其朋友编写替换实现。衡量你的表现并进行比较。
gains/losses 可能重要也可能不重要。