C++中内存的动态管理

我们在C语言中了解到可以在栈区动态开辟空间,并且用完要进行释放,防止内存泄漏。

引入

C++中也有可以进行动态开辟空间和释放空间的操作符new 、delete,虽然C++中也可以用malloc、calloc、realloc、free函数,但是C++中引入了类,而类中会默认生成构造函数和析构函数,如果你想在堆上开辟类类型的空间继续malloc的话,那么该空间的内容就不会自动调用构造函数,而free也不会自动调用析构函数,因为你创建的类指针变量存的是地址,并不是自定义类型,所以程序结束时也不会自动调用析构函数。

对内置类型的内存管理

int main()
{
	// 动态申请一个int类型的空间,不初始化
	int* ptr1 = new int;

	// 动态申请一个int类型的空间并初始化为10
	int* ptr2 = new int(10);

	// 动态申请3个int类型的空间,并初始化为1 2 3
	int* ptr3 = new int[3] {1, 2, 3};

	delete ptr1;//释放单个空间
	delete ptr2;

	delete[] ptr3;//释放连续空间
	return 0;
}

申请和释放单个元素的空间,使用new和delete操作符,申请和释放连续的空间,使用
new[]和delete[]。其实此时对于内置类型而言new与delete相较于malloc与free实现的功能其实是一样的。

对自定义类型的内存管理 

class A
{
public:
	A(int a = 0)
		: _a(a)
	{
		cout << "A():" << this << endl;
	}
	~A()
	{
		cout << "~A():" << this << endl;
	}
private:
	int _a;
};
int main()
{
	A* p1 = (A*)malloc(sizeof(A));
	//A* p2 = new A(1);
	free(p1);
	//delete p2;

	return 0;
}

运行结果:

int main()
{
	//A* p1 = (A*)malloc(sizeof(A));
	A* p2 = new A(1);
	//free(p1);
	delete p2;

	return 0;
}

运行结果:new空间时自动调用构造函数,delete空间时调用析构函数

operator new与operator delete函数

其实操作符new、delete也不是单纯的可以直接实现的,其实,在它们内部还调用着对应的函数operator new 和operator delete是系统提供的全局函数,new在底层调用operator new全局函数来申请空间,delete在底层通过operator delete全局函数来释放空间。

operator new

其实operator new也是通过调用malloc函数实现的,在堆区开辟空间,但是在malloc的基础之上稍稍加了修饰,malloc调用失败会返回NULL,而operator new再次加了判断条件

while ((p = malloc(size)) == 0)//C++中NULL就是0

此时如果为空的话,就会抛异常报错。

 

operator delete

其实向operator new一样,operator delete是通过free来释放空间的。

new和delete的实现原理

其实new和delete操作符也不是仅仅就调用了operator new和operator delete那么简单,其实实际上还调用了类的构造函数,而delete还调用了类的析构函数(delete是先调用析构函数,再调用operator delete函数释放创建的空间)

  • new A[N]的原理

1. 调用operator new[]函数,在operator new[]中实际调用operator new函数完成N个对
象空间的申请
2. 在申请的空间上执行N次构造函数

  • delete[]的原理

1. 在释放的对象空间上执行N次析构函数,完成N个对象中资源的清理
2. 调用operator delete[]释放空间,实际在operator delete[]中调用operator delete来释
放空间

 

 未匹配报错

class A
{
public:
	A(int a = 0)
		: _a(a)
	{
		//cout << "A():" << this << endl;
	}
	~A()
	{
		//cout << "~A():" << this << endl;
		//_a = 0;
	}
private:
	int _a;
};
int main()
{
	A* p = new A[5];
	delete p;

	return 0;
}

此时delete未与new[]匹配,其实应该delete[]p来释放空间的,此时其实就是未匹配的原因报错的。

实际上当你执行:

	A* p = new A[5];

并不是开辟5个A类型大小的空间,实际上会多开辟四个字节存放你要开辟的空间的数字,也就是5,存着的目的也就是通过指针偏移得到这四个字节的数据,从而调用多少次析构函数,所以必须要用delete[]p来释放才行(实际上[]里接收的就是四字节空间存的5)。但是调用operator delete时,指针会偏移指向最前面,释放的所有的空间,包括前面的四个字节。

所以 用delete p来释放空间就肯定会报错啊,不仅仅不会调用5次析构函数,而且主要还不会将前面四字节空间释放,所以就


 

其实我演示的是在x86环境下的,所以就多开辟四字节空间,试试看在x64环境下,貌似是多开辟8字节空间。

 这里A占4个字节,-1就是偏移四字节。

 

 



其实你不写析构函数的话,编译器也不会报错

class A
{
public:
	A(int a=0)
		: _a(a)

	{}
private:
	int _a;
};
int main()
{
	A* p = new A[5];
	delete p;

	return 0;
}

因为编译器进行优化了,没写析构函数,编译器默认生成,但是默认生成也不会执行什么命令,此时编译器就会进行优化,所以就不会再多开辟字节去存放开辟空间的数字了,所以调用operator delete时就是正确的,不会报错,但是可能会内存泄漏(由于没有调足够的析构函数)



欢迎各位莅临指导!!!

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/56256.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

二十三种设计模式第二十二篇--中介者模式

说到这个模式就有趣了&#xff0c;不知道大家在生活中喷到过中介没&#xff1f;其实中介这个词吧&#xff0c;我也说不上好还是坏&#xff0c;有时候他可以帮助人们更快的达到某个目的&#xff0c;但有的时候吧&#xff0c;这个有贼坑人&#xff0c;相信网络上有各种被中介坑的…

Ubuntu20.04进入桌面后左上角光标闪动

T 光标闪烁就是后台一系列活动的简化&#xff0c;它表示后台有一系列活动在进行&#xff0c;只是我们看不到。也因此让我们觉得它像是卡住了。 Y 一开始误以为是由于我安装其他启动动画导致的&#xff0c;后来换回默认的动画发现不是这个原因。 后来我试了各种方法&#xff…

Android复习(Android基础-四大组件)—— Activity

Activity作为四大组件之首&#xff0c;是使用最为频繁的一种组件&#xff0c;中文直接翻译为"活动"&#xff0c;不过如果被翻译为"界面"会更好理解。正常情况&#xff0c;除了Window&#xff0c;Dialog和Toast &#xff0c; 我们能见到的界面只有Activity。…

【硬件设计】模拟电子基础二--放大电路

模拟电子基础二--放大电路 一、基本放大电路1.1 初始电路1.2 静态工作点1.3 分压偏置电路 二、负反馈放大电路三、直流稳压电路 前言&#xff1a;本章为知识的简单复习&#xff0c;适合于硬件设计学习前的知识回顾&#xff0c;不适合运用于考试。 一、基本放大电路 1.1 初始电…

小白到运维工程师自学之路 第六十三集 (dockerfile安装sshd、httpd、nginx)

一、概述 Dockerfile的指令根据作用可以分为两种&#xff0c;构建指令和设置指令。构建指令用于构建image&#xff0c;其指定的操作不会在运行image的容器上执行&#xff1b;设置指令用于设置image的属性&#xff0c;其指定的操作将在运行image的容器中执行。 1、FROM 镜像:T…

Vue3基础(1)

1.简单的vue实例 1.data函数介绍 也可以修改data里的数据 2.自定义函数 调用函数 3.Vue模板语法 &#xff08;1).V-html (2)三目运算符的支持 &#xff08;3&#xff09;对函数的支持 &#xff08;4&#xff09;v-bind 值动态修改 4.指令 1.v-if和v-else的使用

改变C++中私有变量成员的值

1、没有引用的情况&#xff1a; #include <iostream> #include <queue> using namespace std; class Person { public:queue<int>que; public:queue<int> getQueue(){return que;}void push(int a){que.push(a);}void pop(){que.pop();} };int main()…

【vue】组件使用教训

组件使用 报错组件找不到 These dependencies were not found: 遇见的问题 在使用vue的时候&#xff0c;做了一个统计图的功能&#xff0c;引入了chart。 但是在运行项目的时候&#xff0c;直接报错启动不起来&#xff0c;报错内容是 告诉我依赖找不到&#xff0c;然后还试…

2023年第四届“华数杯”数学建模思路 - 案例:粒子群算法

# 0 赛题思路 &#xff08;赛题出来以后第一时间在CSDN分享&#xff09; https://blog.csdn.net/dc_sinor?typeblog 1 什么是粒子群算法&#xff1f; 粒子群算法&#xff08;Particle Swarm Optimization,PSO&#xff09;是一种模仿鸟群、鱼群觅食行为发展起来的一种进化算…

IDEA配置远程docker解释器及无编码提示/关联不到python依赖问题

文章目录 1. 修改docker默认配置以支持远程连接2. 配置docker远程解释器3 .IDE配置project SDK4. 本地代码与Linux目录映射5.运行配置 1. 修改docker默认配置以支持远程连接 vim /lib/systemd/system/docker.service,修改docker启动参数 #ExecStart/usr/bin/dockerd -H fd://…

TIA Portal(博途)V15.0 安装教程

哈喽&#xff0c;大家好&#xff0c;我是雷工。 最近项目上用到博图15.0软件&#xff0c;在虚拟机安装博图软件。下面记录安装过程。 一、安装环境 虚拟机内的Win10系统专业版64位。 二、注意事项 1、安装文件的存放路径不能含中文字符&#xff0c;软件需安装在C盘。 2、操…

RS232自由转Profinet网关扫码枪连接电脑操作

你是否曾经遇到过这样的问题&#xff1a;如何在不编写复杂代码的情况下&#xff0c;将条形码数据上传到PLC&#xff1f;今天&#xff0c;我们将为你揭示一个简单的解决方案&#xff01; 让我们来看看这个神奇的组合&#xff1a;捷米的JM-RS485/232-PN (rs232转Profient网关)和…

容器化安装环境EFK搭建

容器化安装环境 Docker中安装并启动ElasticSearch 前置配置 第一步&#xff1a;在宿主机上执行echo “net.ipv4.ip_forward1” >>/usr/lib/sysctl.d/00-system.conf 2.第二步&#xff1a;重启network和docker服务 [rootlocalhost /]# systemctl restart network &&…

基于量子同态的安全多方量子求和加密

摘要安全多方计算在经典密码学中一直扮演着重要的角色。量子同态加密(QHE)可以在不解密的情况下对加密数据进行计算。目前&#xff0c;大多数协议使用半诚实的第三方(TP)来保护参与者的秘密。我们使用量子同态加密方案代替TP来保护各方的隐私。在量子同态加密的基础上&#xff…

一些高频的C++ cache line面试

C那些事之False Sharing与Cache line 最近看到一段代码&#xff0c;手动做的对齐&#xff0c;于是研究一下不对齐又会带来什么影响&#xff1f; template <typename T> class AtomicWithPadding {private:static constexpr int kCacheLineSize 64;uint8_t padding_befor…

某公共资源交易平台headers逆向

某公共资源交易平台headers逆向 声明逆向目标:寻找加密位置X-Dgi-Req-Nonce和X-Dgi-Req-Timestamp加密分析X-Dgi-Req-Signature加密分析声明 本文章中所有内容仅供学习交流,抓包内容、敏感网址、数据接口均已做脱敏处理,严禁用于商业用途和非法用途,否则由此产生的一切后果…

StarRocks数据库部署全记录(保姆式帮助你初次体验StarRocks)

因业务需要&#xff0c;特此了解StarRocks产品和部署。 接触过程中发现指导资料很稀少&#xff0c;本人将结合官方的手册其他开源博主指导&#xff0c;将第一次接触到的概念和部署流程梳理&#xff0c;得出本文。 已有的资源中对细节介绍欠缺&#xff0c;导致我本人整个过程中花…

JavaWeb+jsp+Tomcat的叮当书城项目

点击以下链接获取源码&#xff1a; https://download.csdn.net/download/qq_64505944/88123111?spm1001.2014.3001.5503 技术&#xff1a;ssm jsp JDK1.8 MySQL5.7 Tomcat8.3 源码数据库课程设计 功能&#xff1a;管理员与普通用户和超级管理员三个角色&#xff0c;管理员可…

Java 解析Excel单元格的富文本

1. 总体介绍 该方法是解析 xlsx 单元格中的富文本&#xff0c;注意不是 xls&#xff0c;xls 的 api 不一样&#xff0c;试了很久没成功。只实现了解析 斜体字、上下标&#xff0c;其它的实现方式应该类似。 2. 具体实现 2.1 代码 package util;import java.io.FileInputStr…

Mac 终端快捷键设置:如何给 Mac 中的 Terminal 设置 Ctrl+Alt+T 快捷键快速启动

Mac 电脑中正常是没有直接打开终端命令行的快捷键指令的&#xff0c;但可以通过 commandspace 打开聚焦搜索&#xff0c;然后输入 ter 或者 terminal 全拼打开。但习惯了 linux 的同学会觉得这个操作很别扭。于是我们希望能通过键盘按键直接打开。 操作流程如下&#xff1a; 1…