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函数去释放空间

相关推荐
LZQqqqqo13 分钟前
C# 中 ArrayList动态数组、List<T>列表与 Dictionary<T Key, T Value>字典的深度对比
windows·c#·list
季春二九14 分钟前
Windows 11 首次开机引导(OOBE 阶段)跳过登录微软账户,创建本地账户
windows·microsoft
芥子沫1 小时前
Jenkins常见问题及解决方法
windows·https·jenkins
cpsvps_net18 小时前
美国服务器环境下Windows容器工作负载智能弹性伸缩
windows
甄超锋18 小时前
Java ArrayList的介绍及用法
java·windows·spring boot·python·spring·spring cloud·tomcat
cpsvps21 小时前
美国服务器环境下Windows容器工作负载基于指标的自动扩缩
windows
网硕互联的小客服1 天前
Apache 如何支持SHTML(SSI)的配置方法
运维·服务器·网络·windows·php
etcix1 天前
implement copy file content to clipboard on Windows
windows·stm32·单片机
许泽宇的技术分享1 天前
Windows MCP.Net:基于.NET的Windows桌面自动化MCP服务器深度解析
windows·自动化·.net
非凡ghost1 天前
AMS PhotoMaster:全方位提升你的照片编辑体验
windows·学习·信息可视化·软件需求