kooafssll5j64066433251.gif
2 Y) W( J. x' B
点击上方蓝色字体,关注我们
6 e& p0 m4 R- B- Znew 与智能指针提供了类型安全、自动管理内存等优点,能够更好地满足大多数场景的需求。- M& |' T f% e8 t
1# m* q+ t/ Q4 R, m9 ~) S
malloc 和 new 的区别# S1 ? x8 W2 [, x
malloc 是 C 语言的内存分配函数,分配的内存是未初始化的,并返回 void* 类型的指针。
5 O, ?$ i* k3 g" w* k
& y$ w3 S& L( Q( l5 s# X要想将 malloc 的返回值赋给特定类型的指针,需要进行显式类型转换,这就缺乏类型安全性。
0 J5 r+ _4 J3 \: W" C- P2 `) v7 ^* S2 r( e
而 C++ 的 new 操作符会自动调用构造函数,并返回指定类型的指针,避免了类型转换问题,增加了类型安全性。
2 |" P4 y, |4 \+ `# n/ N4 Q# c! Z3 E) k5 ^9 ^3 d1 L I1 W
new 不仅分配内存,还会调用类的构造函数来初始化对象。而 malloc 仅分配内存,不做初始化。& q4 O& g0 x7 K9 c/ a5 j
, }# h. [4 c7 \3 V- Y; ?' `
这意味着使用 malloc 时,我们无法直接管理对象的生命周期,必须手动调用构造函数和析构函数(这几乎不常见且容易出错)。" q6 [+ y$ z) J* k; H
2; b) A+ R1 H4 n0 U9 |4 `, d
智能指针和现代 C++ 内存管理
, r% \4 [* b0 `8 V- K- A, lC++11 引入了智能指针,如 std::unique_ptr 和 std::shared_ptr,它们通过 RAII(Resource Acquisition Is Initialization)机制帮助自动管理内存。
. i9 y; \ r% w4 K1 d3 m! }: S
. N$ h7 N8 A' ^1 \3 p这让开发者几乎不需要直接调用 new 或 delete,大幅降低了内存泄漏的风险。更不用说 malloc 和 free 了。( e# v, `& C9 O" j" D: v" o
5 L. C$ d7 [+ }" D
例如:/ |3 ]0 p; y) O- J6 i- s/ j
/ J: f8 F5 W) R2 L" }0 x7 ^std::unique_ptrptr = std::make_unique(10); // 自动管理内存
1 g) i4 H5 u8 E* E" G使用智能指针,内存会在指针超出作用域时自动释放,无需手动调用 free。2 ]1 ?0 i+ Q& i# @% M8 j( X# @
3' C( R# x) N, k4 ^6 r' ?0 t3 `
使用 malloc 的场景& H4 e% U' J* ~1 e
尽管现代 C++ 提供了更好的内存管理工具,但在少数特定场景下,malloc 仍然可能有其用武之地。/ A8 i( D- [) z% n9 W
+ c* f+ x/ J8 x' _
如果你需要与大量 C 代码或使用 C 库的项目协作(如某些底层嵌入式系统开发),使用 malloc 会更容易实现与 C 代码的无缝交互。
, E; v7 l& i$ t2 w# X6 r: h; f
5 w" @. y' I0 g- K" F. o- K, o在某些性能要求极高的系统中,为了精细控制内存布局和管理,开发者可能会实现自定义的内存分配器。9 B! l5 F6 A. i c: P6 r
2 n# F6 F w0 b# {* N# S. B7 ~
自定义分配器的内部实现可能基于 malloc 这种低级分配函数,以便更灵活地优化内存操作。
- R! Z' Y! F$ N+ X. T, J$ M4 E, I' L3 S1 u
不需要构造函数的分配:对于不需要初始化的原始数据块或 POD(Plain Old Data)类型数据,malloc 有时可能更加直接,比如用于分配一个不需要构造和析构的字节缓冲区。/ p$ n1 H; N( c) s1 k: P
40 t# w. ?* E5 W; O+ l
实际代码示例) o; a8 c' H1 B3 F- v4 Z1 b2 `
C++ 的方式
7 k2 K7 E, [( K4 j: Z3 z. O {! Tstruct MyClass { MyClass() { std::cout "Constructed {2 D' c& c* m, i( a, Z, q2 A
"; } ~MyClass() { std::cout "Destructed# u1 h( n) E$ u1 }& U2 _5 U# R
"; }};
7 D) Y. Y9 G5 \" pint main() { auto ptr = std::make_unique(); // 自动调用构造/析构}
6 ?7 [; |" ]$ J使用 malloc 的方式(不推荐,除非必须兼容 C)
- F4 S" p5 [9 s/ t S0 ]1 wstruct MyClass { MyClass() { std::cout "Constructed
" m( W2 x3 K7 B: c" V"; } ~MyClass() { std::cout "Destructed
6 [ f7 P4 s# a. [) F+ D" h' W"; }};
/ X9 v$ r5 M; ?% @1 O6 ?' f( F% xint main() { MyClass* ptr = (MyClass*)malloc(sizeof(MyClass)); new(ptr) MyClass; // 手动调用构造函数 ptr->~MyClass(); // 手动调用析构函数 free(ptr);}
! ?$ m9 ~5 P% p7 [在第二种方式中,手动管理构造和析构显得繁琐且不直观,容易引入内存泄漏或未定义行为。! y. e" Y/ w. ~- ~
u33aa4nltj464066433351.jpg
" `' [$ O5 p( i; F
4kkspejwcgh64066433451.gif
# Y( j' g& Q; O- ]- l) |( C点击阅读原文,更精彩~ |