C++的内存管理

引言:回顾malloc

C语言的内存管理有malloc,calloc,realloc,free。

前三者的区别分别是:

申请 申请+初始化为0 扩容

malloc的原理:先向操作系统申请一大块堆内存,在其中维护空闲块链表(每块带header记录着大小和状态),malloc(n)遍历链表,使用first-fit策略寻找合适的块并返回。

C++对上述进行了改进,使用 new / delete操作符进行动态内存管理。

new / delete

基本用法

cpp 复制代码
int main() 
{
    int* ptr = new int; //动态申请int类型的空间
    int* ptr1 = new int(10); //动态申请并初始化为10
    int* ptr2 = new int[10]; //申请连续的10个int空间
    int* ptr3 = new int[10]{ 1,2,3,4,5,6,7,8,9,0 }; //申请连续空间并初始化

    delete ptr;
    delete ptr1;
    delete [] ptr2; // new 的[] 一定要和 delete对应
    delete[] ptr3;

    return 0;
}

关于为什么delete要加 \[\] 的问题

原因与new为何无需手动计算大小有关。

简单来说,new申请的空间的头部会留有一个整形用于存储元素个数,如果在delete的时候,不加 \[\] ,delete就会进行单对象处理,或者从错误的地址开始释放。

new / delete 和 malloc / free 的区别

new / delete与 malloc / free 最大的区别体现在对自定义类类型的操作上。

new / delete对自定义类型操作时,会分别调用其构造函数和析构函数。

cpp 复制代码
class test3
{
private:
    int _a;

public:
    test3(int a = 0)
        :_a(a)
    {
        cout << "调用test3的构造函数" << endl;
    }
    
    ~test3()
    {
        cout << "调用test3的析构函数" << endl;
    }
};
int main() 
{
    test3* ptr1 = (test3*)malloc(sizeof(test3));
    test3* ptr2 = new test3;

    delete ptr2;
    free(ptr1);


    return 0;
}

输出结果为:

operator new / operator delete

operator new / operator delete是系统提供的全局函数,new / delete的底层便是调用它们。而operator new 也是分别使用 malloc 来申请空间的,不会调用构造函数,失败时抛异常。

operator delete 最终通过free释放空间。

至此,new / delete的底层原理就显而易见了。

对于自定义类型,new 分为两步:

1.使用operator new 申请空间

2.调用构造函数

delete:

1.调用析构函数

2.使用operator delete

定位new表达式:placement-new

placement-new是对一个已分配的内存空间中调用构造函数初始化一个对象。

比如,你用malloc申请了一块空间,你想在上面初始化对象,但是构造函数无法像普通的成员函数那样,通过malloc返回的指针调用,它只在创建对象时,由编译器调用,所以我们得使用定位new表达式

格式如下:

cpp 复制代码
int main() 
{
    test3* ptr = (test3*)malloc(sizeof(test3)); //空间已分配,但是没有对象
    new(ptr)test3; // 调用构造函数 格式:new(地址)类型
    ptr->~test3();
    free(ptr);
    return 0;
}

总结:malloc / free 与 new / delete 的区别

1.malloc不会调用构造函数,new会

2.malloc默认返回void*,需强转, new不用

3.malloc需要手动计算大小,new只需传类型,多个时只需指明个数

4.malloc是函数,new是操作符

5.malloc失败时,返回NULL,因此必须判空,而new是抛异常

6.malloc空间无法自动初始化,new可以

相关推荐
choumin2 小时前
C++中std::move和std::forward的关系和区别
c++·std move·std forward·关系和区别
程序猿编码2 小时前
YOLOv5/v7/YOLOX 全支持:基于 TensorRT 的工业视觉推理底座详解
c++·yolo·机器学习·推理·模型推理
kyle~2 小时前
C++ 原子操作、内存模型与无锁并发编程
linux·开发语言·c++·操作系统
another heaven2 小时前
【C/C++ C++ 面向对象架构的五大特点与能力场景:封装、继承、多态、抽象与 RAII(含实战案例)】
c语言·c++·架构
NoteDeep 深度笔记2 小时前
排期看不出冲突?把任务表切成甘特图
笔记·个人开发·甘特图·笔记应用·深度笔记·云笔记
努力努力再努力wz3 小时前
【C++ 高阶系列】C++ 高性能网络编程:当 Reactor 遇见协程:从 epoll 回调到异步 MySQL,彻底打通任务挂起与恢复
网络·c++·mysql
霍霍的袁4 小时前
【C++11】左值右值引用与移动语义详细笔记(左值右值、右值引用、移动构造、移动赋值、引用折叠、万能转发)
c++·笔记·学习·visual studio
MandalaO_O4 小时前
SpringMVC 异常处理 & 拦截器
笔记
布莱克6054 小时前
C++ 中 unordered_set 与 unordered_map 有什么不同?一篇讲透
开发语言·c++·哈希
鶴哥只手遮天4 小时前
AFSIM 2.9.0 深度解析:架构、原理与工程实践-第 1 章 项目全景与代码地图
c++