【c++】malloc和new

【c++】malloc和new

1. 内存分配与初始化

malloc/free

  • 分配方式
    malloc堆区申请一块指定大小连续的内存空间,并返回该内存区域的起始地址(类型为 void*)。
  • 初始化
    malloc 只分配内存,不会初始化(也就是说,内存中的数据内容是未定义的)。
  • 使用方式
    • 调用时需要手动计算所需的字节数(例如:malloc(n * sizeof(T)))。
    • 返回的指针通常需要在 C++ 中强制转换成相应类型。
  • 错误处理
    如果分配失败,malloc 会返回 NULL,因此调用者需要进行判空处理。

new/delete

  • 分配方式
    • 关键字形式的 new
      当使用 new Type(arguments) 时,编译器首先根据类型自动计算出所需的内存大小,然后调用内部的分配函数(底层往往会调用 malloc(或等效的内存分配函数)来获得内存。接着使用()中的值初始化申请的内存空间,最后返回地址
    • 函数形式的 operator new
      也就是直接调用内置的分配函数,仅负责申请内存,不调用构造函数。
    • 定位(Placement)new
      对只限定的空间进行初始化
  • 初始化
    • 关键字 new 会在分配内存后自动调用构造函数,对内存进行初始化。
    • 函数形式的 operator new仅负责内存分配,不进行对象的构造。
  • 返回值
    返回的是正确类型的指针,不需要强制类型转换。
  • 错误处理
    如果内存分配失败,关键字 new 会抛出异常(通常为 std::bad_alloc),而不是返回 NULL。

delete时为了知道delete的区域 会有28字节的头部信息 以及四字节的上越界 四字节的下越界标记
因此申请空间越小负担越大内存利用率越低


2. 使用上的差异

  • 大小计算

    • malloc:调用者必须手动计算内存大小;例如:malloc(10 * sizeof(int))
    • new:编译器自动根据类型计算所需大小;例如:new int[10] 自动分配足够空间。
  • 初始化行为

    • malloc:不会对分配的内存进行初始化,使用前可能需要手动初始化(或者使用 calloc 来分配并初始化为 0)。
    • new:会自动调用构造函数,对对象进行初始化。
  • 错误检查

    • malloc:返回 NULL 后需要手动判空。
    • new:分配失败时会直接抛异常(除非使用 nothrow 版本)。
  • 内存释放

    • malloc** 分配的内存必须用 free() 来释放。
    • new 分配的内存必须用 delete(或 delete[])来释放,这样不仅回收内存,还会调用对象的析构函数。
  • 类型转换

    • malloc:只分配内存,不做初始化;需要手动计算大小;返回 void*,调用者需要进行类型转换。
    • new:自动计算大小,分配内存后自动调用构造函数进行初始化;返回具体类型的指针,无需类型转换。

3. 内部实现与内存池

  • 内存分配的底层系统调用
    不论是 malloc 还是 new 内部的 operator new,最终都会调用类似 sbrk(适用于较小的内存分配)或 mmap(适用于大块内存分配,比如通常以 128KB 为界限)这样的系统调用来扩展进程的虚拟内存空间。

  • 内存池和额外开销

    • 当使用 sbrk 分配内存时,释放的内存并不一定立即归还给操作系统,而可能被保存在内部的内存池中以便下次重用;这就会在分配的小内存块中附加上(例如头部 28 字节和尾部 4 字节之类的)额外的管理信息,从而降低小块内存的利用率。
    • 当使用 mmap 分配大块内存时,释放后通常会将内存归还给操作系统。

你可能感兴趣的:(c++,c++,开发语言)