new和malloc的区别

new

定位new

在C++中,new操作符用于在 (heap)上动态分配内,存并返回指向该内存的指针。

当你使用new来分配内存时,如果你希望定位(placement)这个内存分配到特定的地址上,你需要使用"定位new"(placement new)语法。

定位new允许你指定对象应该被构造的内存地址。

这在某些特定场景下非常有用,比如当你已经有了一块分配好的内存,希望在这块内存上直接构造对象,而不是重新分配内存。

定位new的基本语法如下:

new (place_address) Type(initializer_list);

这里,place_address是一个指向已分配内存的指针,Type是要构造的对象的类型,initializer_list(可选)是传递给对象构造函数的参数列表。

示例

假设你已经有了一个字符数组,你想在这个数组上构造一个std::string对象(虽然这在实际中并不常见,因为std::string会管理自己的内存,这里仅作为演示):

cpp 复制代码
#include <iostream>
#include <new> // 需要包含这个头文件来使用定位new

int main() {
    char buffer[256]; // 分配一个字符数组
    
    // 注意:这里实际上并不推荐在字符数组上构造std::string,因为std::string会管理自己的内存
    // 这里仅作为定位new的示例
    std::string* pStr = new (buffer) std::string("Hello, placement new!");

    std::cout << "String: " << *pStr << std::endl;

    // 使用完后,需要显式调用析构函数来清理资源
    pStr->~std::string();

    // 注意:此时buffer中可能包含未定义的数据,因为std::string的析构函数已经清理了它
    // 但在某些情况下,你可能需要处理或重用buffer中的数据

    return 0;
}

重要注意事项:

使用定位new时,你需要确保指定的地址是有效的,并且足够大以容纳你想要构造的对象。

使用完定位new构造的对象后,你需要显式调用该对象的析构函数来清理资源 。因为定位new不会调用全局的operator delete来自动清理资源。

定位new在底层编程和特定场景下非常有用,但在普通应用中应该谨慎使用,以避免内存泄漏和未定义行为。

new关键字:

malloc.realloc.calloc

malloc、calloc和realloc是用来开辟我们的空间的,realloc和前两个不同的是:他能用来扩容,也就是调整空间;

他们只是会为我们开辟空间,并不会为我们的空间初始化,calloc是可以将我们的空间初始化为0的,但是对于我们的自定义类型,他们并不会自动的调用我们的构造函数初始化;

三个函数的用法:

malloc:

size是开辟的空间的字节数。

realloc:

ptr是原来的旧空间的起始地址,

size是开辟空间的字节数。

realloc也可以进行开辟空间。

calloc:

num:是开的类型的个数。

size:是开的类型的大小(字节)。

calloc是会进行初始化的,将我们的所有的值初始化为0;

malloc/free和new/delete的共同点是:

都是从堆上申请空间,并且需要用户手动释放。

不同的地 方是:

  1. malloc和free是函数,new和delete是操作符

  2. malloc申请的空间不会初始化,new可以初始化

  3. malloc申请空间时,需要手动计算空间大小并传递,new只需在其后跟上空间的类型即可, 如果是多个对象,[]中指定对象个数即可

  4. malloc的返回值为void*, 在使用时必须强转,new不需要,因为new后跟的是空间的类型

  5. malloc申请空间失败时,返回的是NULL,因此使用时必须判空,new不需要,但是new需 要捕获异常

  6. 申请自定义类型对象时,malloc/free只会开辟空间,不会调用构造函数与析构函数,而new 在申请空间后会调用构造函数完成对象的初始化,delete在释放空间前会调用析构函数完成 空间中资源的清理

new T[N]的原理

  1. 调用operator new[]函数,在operator new[]中实际调用operator new函数完成N个对 象空间的申请

  2. 在申请的空间上执行N次构造函数

我们的new 的内部也是使用了malloc等函数去给我们开辟空间。

注意我们如果是调用的new去开辟空间,而不用对应的delete去释放空间的话,可能会程序崩溃,因为我们的new[]在进行开辟空间的时候可能会多开辟空间,为了记录我们调用了几次构造函数,以方便我们去调用几次析构函数。

delete[]的原理

  1. 在释放的对象空间上执行N次析构函数,完成N个对象中资源的清理

  2. 调用operator delete[]释放空间,实际在operator delete[]中调用operator delete来释 放空间

我们的delete内部也是调用了我们的free函数去释放空间

相关推荐
电手12 分钟前
Win10停更,Win11不好用?现在Mac电脑比Win11电脑更便宜
windows·macos·电脑·mac
拾回程序猿的圈圈∞42 分钟前
PyCharm项目和文件运行时使用conda环境的教程
windows·pycharm·conda
波点兔1 小时前
【亲测有效 | Cursor Pro每月500次快速请求扩5倍】(Windows版)Cursor中集成interactive-feedback-mcp
windows·mcp·cursor pro
饮长安千年月3 小时前
JavaSec-SSTI - 模板引擎注入
java·windows·安全·web安全·网络安全·系统安全·安全架构
字节高级特工5 小时前
【Linux篇】0基础之学习操作系统进程
linux·运维·服务器·数据结构·windows·学习·list
Amo Xiang14 小时前
Python 解释器安装全攻略(适用于 Linux / Windows / macOS)
linux·windows·python·环境安装
小邓儿◑.◑20 小时前
C++初阶 | 模板
网络·c++·windows
豆芽脚脚20 小时前
spel 多层list嵌套表达式踩坑记
windows·list·spel
饮长安千年月1 天前
玄机-第六章 流量特征分析-蚂蚁爱上树
windows·计算机网络·web安全·网络安全·系统安全·安全架构
mrbone111 天前
Linux-linux和windows创建新进程的区别以及posix_spawn
linux·运维·windows·多进程·fork