当前位置: 首页 > news >正文

【C++初阶】内存管理

目录

C++内存分布

C++内存管理方式

new和delete

对内置类型的使用

对自定义类型的使用

原理

内置类型:

自定义类型:

匹配问题

内置类型:

自定义类型:

意义:

1、析构函数调用次数

2、错误位置释放

注:不需要匹配的情况

new/delete和malloc/free的区别


C++内存分布

C++内存管理方式

new和delete

C语言的内存管理方法在C++中也可以使用,但是在一些地方是无法处理的而且使用起来会比较麻烦,所以C++就提出了自己的管理方法:new和delete

对内置类型的使用

int main()
{
    int* a1 = new int;//动态申请一个int类型的空间
    delete a1;//释放空间
    
    int* a2 = new int(1);//动态申请一个int类型的空间,并初始化为1
    delete a2;

    int* a3 = new int[10];//动态申请十个int类型的空间
    delete[] a3;
    
    return 0;
}

对于连续申请的多个空间的初始化

int main()
{
    int* a = new int[10]{1,2,3};//动态申请十个int类型的空间,初始化前三个,其他的自动赋值为0
    delete[] a3;
    
    return 0;
}

对自定义类型的使用

class A
{
public:
    A(int a)
	{
        _a1 = _a2 = a;
	}
	~A()
	{
		cout << "~A()" << endl;
	}
private:
	int _a1;
	int _a2;
};

int main()
{
    A* a1 = new A;
    delete a1;
    A* a2 = new A(1);
    delete a2;
    A* a3 = new A[10]{1,2,3};
    delete[] a3;

    return 0;
}

与内置类型不同的是,new/delete对于自定义类型对象不仅会开辟/释放空间,还会调用构造函数和析构函数,初始化了几个就调用几次构造函数和对应的析构函数

class A
{
public:
    A(int a)
	{
        _a1 = _a2 = a;
	}
    A(int a1 = 0, int a2 = 0)
	{
		cout << "A()" << endl;
		_a1 = a1;
		_a2 = a2;
	}
	~A()
	{
		cout << "~A()" << endl;
	}
private:
	int _a1;
	int _a2;
};

int main()
{
    A* a = new A[10]{{1,1},{2,2},{3,3}};
    delete[] a;

    return 0;
}

在这里a的实现要依靠默认构造函数/或对应有参构造函数,如果没有的话就会报错

原理

内置类型:

对于内置类型,new/delete与malloc/free是相同的,唯一不同的是,new在申请空间失败后会自动抛异常,而malloc要自己手动实现来验证是否申请失败

自定义类型:

new的原理其实就是operator new() + 构造函数

先调用operator new(),再调用构造函数

operator new()函数:进行空间申请

构造函数:初始化对象

而operator new()函数其实就是由malloc()函数组成的,但和malloc()不同的是,它不需要在申请空间后要自己检查是否申请成功,operator new()函数会自己判断,然后根据申请成功与否来进行抛异常(在这里我们就不细讲抛异常,会在后文在做详细讲解)

delete的原理是operator delete() + 析构函数

先进行析构,再调用operator delete()

析构函数:将对象指向资源释放

operator delete():销毁空间

而operator delete()函数的底层就是free()函数

至于new T[N]和delete[]的原理和new/delete是一样的,只不过要根据申请了多少个空间来进行对应次数的构造函数和析构函数的调用

所以new/delete在底层其实就是malloc/free,不过是在malloc和free的基础上进行了一些封装,加了一些功能

匹配问题

在new和delete的匹配问题上,内置类型和自定义类型是不相同的

内置类型:
int main()
{
    int* a1 = new int;//动态申请一个int类型的空间
    delete a1;//释放空间

    int* a3 = new int[10];//动态申请十个int类型的空间
    delete[] a3;

    //delete a3;//这样也可以进行a3的释放,内置类型可以考虑不加[]
    
    return 0;
}
自定义类型:
class A
{
public:
    A(int a)
	{
        _a1 = _a2 = a;
	}
	~A()
	{
		cout << "~A()" << endl;
	}
private:
	int _a1;
	int _a2;
};

int main()
{
    A* a1 = new A;
    delete a1;

    A* a2 = new A(1);
    delete a2;

    A* a3 = new A[10]{1,2,3};
    delete[] a3;
  //delete a3;//error

    return 0;
}

 之所以会导致这样的问题,是因为一个这样的机制:

对于new一个自定义类型对象,在new[N]时,不仅会给对象申请一份空间,还会对[]中的N申请一块空间,我们可以在Vs上进行验证:

我们也可以从这个对象的大小来判断,原本根据A这个类来判断a3的大小应该是80个字节,而这里却是84个字节,那多出来的4个字节就是为[]中的数字开辟的空间

意义:

那有人就会有疑惑,开辟这个空间的意义在哪?

1、析构函数调用次数

我们在前面知道new了几个空间就需要调用几次构造函数和几次析构函数,new当然知道要调用几次构造函数(因为[]里面写好了),当时operator却不知道要调用几次析构函数啊!

所以就要开辟一块空间给[]中的数字,来告诉[],然后在operator后面加上[]就可以让operator调用正确次数的析构函数

但这种情况下编译器还不会报错

2、错误位置释放

在外面delete这个对象开辟的空间时,如果不加[],那我们就是从对象的地址开始释放,而前面的空间就无法释放,这就是最严重的问题:从错误地址开始释放,这样就会导致编译器报错

注:不需要匹配的情况

当类中没显式实现析构函数的情况下,不加[]是可以正常运行的,因为不会调用析构函数,而在这情况下,也不会给[]中数字开辟空间,会直接从对象首地址开始释放

在这里就涉及到编译器的优化,因为没有显式实现析构函数,所以编译器在不需要释放什么资源的情况下就会优化掉自己的生成的默认析构函数

new/delete和malloc/free的区别

malloc/freenew/delete的共同点是:都是从堆上申请空间,并且需要用户手动释放。

不同的地方是:

1. mallocfree是函数,newdelete是操作符

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

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

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

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

要捕获异常

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

相关文章:

  • PyTorch深度学习框架60天进阶学习计划第16天:循环神经网络进阶!
  • 【CSS3】练气篇
  • RabbitMQ消息队列中间件安装部署教程(Windows)-2025最新版详细图文教程(附所需安装包)
  • 常用无功功率算法的C语言实现(二)
  • 算法题(89):单项链表
  • 电容与电感以及其典型的电路
  • 物联网-铁路局“管理工区一张图”实现方案
  • Ubuntu切换lowlatency内核
  • 详解动态规划算法
  • Java并发 vs 并行:本质区别与应用场景全解析(易混概念)
  • HCIA-DHCP
  • 洛谷P4269 [USACO18FEB] Snow Boots G
  • 高效Android MQTT封装工具:简化物联网开发,提升性能与稳定性
  • 【项目日记(十)】瓶颈分析与使用基数树优化
  • Deepseek R1 等大模型本地部署+本地知识库 学习笔记
  • Unity Dots环境配置
  • 用AI学编程2——python学习1
  • 消息队列信号量介绍与IPC原理
  • 大模型开发(五):P-Tuning项目——新零售决策评价系统(下)
  • 从自己电脑的浏览器访问阿里云主机中运行的LLaMA-Factory webui
  • 展馆展示设计公司排名推荐/seo快速排名点击
  • 做几个网站好/app渠道推广
  • 做gif表情包的网站/百度登录个人中心官网
  • 反向代理/大兵seo博客
  • 大型企业网站开发/aso优化软件
  • 免费用手机建立网站/常见的网络营销方法有哪些