C++内存管理
文章目录
- 1. c的内存管理例题
- 2.c++管理方式
- 1.c++的内置类型
- 1.申请一个空间并初始化
- 2.申请连续的空间并初始化
- 3.总结
- 2.c++的自定义类型
- 2.总结
- 3.operator new与operator delete函数
- 4.new和delete的实现原理
- 1.内置类型
- 2.自定义类型
- 内存泄露问题&&delete先析构的原因
- 编译器实现机制问题
- 5.定位new
- 定位new的使用场景
- 6.malloc/free与new/delete的区别
- 1.共同点
- 2.不同点
- 用法角度
- 底层原理角度
1. c的内存管理例题
下面这道例题用于检测c的内存管理的学习程度,又或者说是学到这里c究竟忘了多少…
int globalVar = 1;
static int staticGlobalVar = 1;
void Test()
{static int staticVar = 1;int localVar = 1;int num1[10] = { 1, 2, 3, 4 };char char2[] = "abcd";const char* pChar3 = "abcd";int* ptr1 = (int*)malloc(sizeof(int) * 4);int* ptr2 = (int*)calloc(4, sizeof(int));int* ptr3 = (int*)realloc(ptr2, sizeof(int) * 4);free(ptr1);free(ptr3);
}
/*1. 选择题:选项: A.栈 B.堆 C.数据段(静态区) D.代码段(常量区)globalVar在哪里?__C__ staticGlobalVar在哪里?__C__staticVar在哪里?_C___ localVar在哪里?___A_num1 在哪里?__A__char2在哪里?____ *char2在哪里?___pChar3在哪里?____ *pChar3在哪里?____ptr1在哪里?____ *ptr1在哪里?____- 填空题:sizeof(num1) = ____; sizeof(char2) = ____; strlen(char2) = ____;sizeof(pChar3) = ____; strlen(pChar3) = ____;sizeof(ptr1) = ____;*/
- globalvar: 是全局变量 处于静态区
- staticGlobalvar :是全局静态变量 ,处于静态区
- staticvar : 是局部静态变量 ,处于静态区
- localvar: 是局部变量 ,处于 栈
- num1 : 是一个局部的数组,处于栈
- char2 是一个字符数组 ,处于栈
- *char2 :char2是一个数组名,由于既不单独放在sizeof内部,也没有取地址,数组名作为首元素地址,*char2是第一个元素,而整个数组处于栈中,所以 *char2处于栈
- pchar3: 是一个由const修饰的字符类型指针,指针指向的内容不能改变, 说明"abcd"是一个常量字符串,内容不能被修改,处于栈
- *pchar3 :由于"abcd"是一个常量字符串,pchar3指向常量字符串,*pchar3 处于常量区
- ptr1 :是一个指向堆开辟空间的指针,处于栈
- *ptr :是为堆开辟的空间 ,处于堆
- sizeof(num1): 单独当在sizeof内部,数组名代表整个数组,sizeof(num1)=40
- - sizeof(char2):单独当在sizeof内部,数组名代表整个数组,abcd\0,sizeof(char2)=5
- - sizeof(pChar3):pChar3是一个指针,所以sizeof(pChar3)=4/8
- strlen(pChar3):pChar3代表首元素地址,strlen为从给予的地址开始 到’\0’结束,strlen(pChar3)=4
- - sizeof(ptr1):ptr1是一个指针 ,sizeof(ptr1)=4/8
2.c++管理方式
1.c++的内置类型
1.申请一个空间并初始化
#include<iostream>
using namespace std;
int main()
{
//int*ptr1=new int;//申请1个int的空间int* ptr = new int(10);//申请10个int的空间并初始化为10delete ptr;//释放单个空间return 0;
}
2.申请连续的空间并初始化
#include<iostream>
using namespace std;
int main()
{//int* ptr = new int(10);//int* ptr1 = new int[10];//申请10个int的空间int* ptr = new int[10] {1, 2, 3, 4};//申请10个int的空间并初始化delete []ptr;//释放连续空间return 0;
}
这里相当于部分初始化,只初始化了前4个空间,其他空间默认为0
3.总结
申请和释放单个元素的空间,使用new和delete操作符,申请和释放连续的空间,使用new[]和delete[]
2.c++的自定义类型
#include<iostream>
using namespace std;
class A
{
public:A(int a = 0): _a(a){cout << "A():" << this << endl;}~A(){cout << "~A():" << this << endl;}
private:int _a;
};int main()
{A* p = (A*)malloc(sizeof(A) * 10);free(p);A* p1 = new A[2];delete[]p1;return 0;
}
- 申请2个A类型的空间,调用2次构造函数释放空间,并调用2次析构函数
- 虽然写入了malloc在堆开辟10个A类型空间,free释放空间,但是没有调用构造和析构函数
2.总结
在申请自定义类型的空间时,new会调用构造函数,delete会调用析构函数,而malloc与free不会。
3.operator new与operator delete函数
- operator new与operator delete函数是库里面提供的两个全局函数,不是运算符重载
new和delete是用户进行动态内存申请和释放的操作符,new在底层调用operator new全局函数来申请空间,delete在底层通过operator delete全局函数来释放空间。
#include <iostream>
using namespace std;
#include<iostream>
using namespace std;
class A
{
public:A(int a = 0): _a(a){cout << "A():" << this << endl;}~A(){cout << "~A():" << this << endl;}
private:int _a;
};int main()
{//申请空间 operator new 封装 malloc//在用operator delete p1指向空间A* p1 = new A;delete p1;//申请空间 operator new 封装 malloc//在用operator delete []p2指向空间A* p2 = new A[10];delete []p2;return 0;
}
\
4.new和delete的实现原理
1.内置类型
- 对于是内置类型,malloc/free与new/delete功能基本一致,但new/delete申请和释放的是单个元素的空间,new[]和delete[]申请的是连续空间
#include<iostream>
using namespace std;
int main()
{int* p1 = (int*)operator new(sizeof(int));//new失败抛异常int* p2 = (int*)malloc(sizeof(int));if (p2 == nullptr)//malloc失败返回空{perror("malloc fail");}return 0;
}
- new机制与malloc也不同,new申请空间失败会抛异常,而malloc失败返回nullptr
2.自定义类型
#include<iostream>
using namespace std;
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 = new A;//先创建空间,在调用构造函数,delete p1;//delete先调用析构函数,在释放空间//-----------------------------------A* p2 = new A[10];//先创建空间,在调用构造函数10次delete[]p2;//delete先调用析构函数10次,在释放空间return 0;
}
- new先申请一个A的空间,再调用构造函数,delete先调用析构函数,再释放空间
- new先申请10个A类型的空间,再调用构造函数10次,delete先调用析构函数10次,再释放空间
内存泄露问题&&delete先析构的原因
class stack
{
public:stack()//构造{cout << "stack()" << endl;_a = new int[4];_top = 0;_capacity = 4;}~stack()//析构{cout << "~stack()" << endl;delete[] _a; _top = _capacity = 0;}
private:int* _a;int _top;int _capacity;
};
int main()
{stack p;stack*p1 = new stack;delete p1;return 0;
}
- 类的实例化对象生成p,在栈上,调用构造函数,在堆上开辟了4个stack类型的数组
- p1是一个指针,在栈上,指向在堆上申请的一个stack, 再调用构造函数,_a=new
stack[4],_a再次指向在堆上申请的4个stack类型的数组,
所以必须先调用析构函数,在释放空间
若将delete p1改为 free(p1),会少调用析构函数,直接释放stack空间
导致无法释放堆上申请的4个stack类型的数组,从而导致内存泄露
编译器实现机制问题
#include<iostream>
using namespace std;
class A
{
public:A(int a = 0): _a(a){cout << "A():" << this << endl;}~A(){cout << "~A():" << this << endl;}
private:int _a;
};int main()
{A* p = new A[10];//delete p;//错误//free(p);//错误delete []p;//正确return 0;
}
正常来说,A*p=new A[10],我们知道会调用10次构造函数,但是delete [] p是怎么知道要调用10次析构函数的呢?
- 自定义类型A的大小为4个字节,申请10个A类型的数组,会开辟40个字节的空间,但是编译器会多开辟4个字节,用于存储个数 10,个数10是给delete时候用的
- free ( p ) / delete p 时,释放的位置不对,所以会报错
- delete[],就从当前指针p指向位置的地址往前减去4个字节,取到这个值(例如10),通过这个值就知道调用多少次析构函数
- 最终指针指向释放位置,从释放位置开始释放空间
5.定位new
class A
{
public:A(int a = 0): _a(a){cout << "A():" << this << endl;}~A(){cout << "~A():" << this << endl;}
private:int _a;
};
int main()
{A* p = (A*)malloc(sizeof(A));//开好一块空间if (p == nullptr){perror("malloc fail");}//定位newnew(p)A(1);//将p对象中的_a初始化为1p->~A();free(p);return 0;
}
- 对一块已有的空间进行初始化
定位new的使用场景
-
操作系统的堆因为给所有的地方提供,所以会慢一些
-
以前使用malloc/new申请内存,都是去操作系统的堆上申请的,直接申请
-
为了提高效率,申请内存去内存池中寻找,而内存池中内存也是堆上的,
如果内存池上有就直接返回,如果没有就会去堆上找,比如需要4个字节,内存池会申请大块的内存,储备到内存池中,下一次来申请内存,就能在内存池中找到 -
当在内存池中要的内存,而内存池要的内存没有初始化,所以需要定位new
6.malloc/free与new/delete的区别
1.共同点
都是从堆上申请空间,并且需要用户手动释放
2.不同点
用法角度
- 1.malloc和free是函数,new和delete是操作符
- 2.malloc申请的空间不会初始化,new可以初始化
- 3.malloc申请空间时,需要手动计算空间大小并传递,new只需其后跟上空间的类型即可,如果是多个对象时,[]指定对象个数即可
- 4.malloc返回值为void*,在使用必须强转,new不需要,因为new后跟的是空间类型
底层原理角度
- malloc申请空间失败时,返回的是NULL,因此使用时必须判空,new失败会抛异常
- 申请自定义类型对象时,malloc/free只会开辟空间,不会调用构造和析构函数,而new申请空间后会调用构造函数完成对象的初始化,delete在释放空间会调用析构函数完成空间中的资源的清理
相关文章:
C++内存管理
文章目录1. c的内存管理例题2.c管理方式1.c的内置类型1.申请一个空间并初始化2.申请连续的空间并初始化3.总结2.c的自定义类型2.总结3.operator new与operator delete函数4.new和delete的实现原理1.内置类型2.自定义类型内存泄露问题&&delete先析构的原因编译器实现机制…...
电子招投标系统源码之 —采购数字化转型快人一步,以大数据支撑供应链管理未来
采购数字化转型快人一步,以大数据支撑供应链管理未来 招标采购为主的一站式全流程数字化采供协同。平台满足询比价、招标、竞价、拍卖、协议直采、商城采购等多种采购定价方式,采购过程全程留痕可追溯。平台支持企业通过WEB、APP、小程序等终端完成采购需…...
ie获取cookie数据,中文乱码;cookie中文乱码终极解决办法
终极解决办法 cookie存中文数据是会出现乱码的,所以在存数据前,得先“编码”,取的时候先“解码” JS方法-编码:encodeURI("你好") 结果:"%E4%BD%A0%E5%A5%BD"JS方法-解码:decodeURI(&…...
day16_关键字this和super丶就近原则和追根溯源原则
this关键字 含义:this代表当前对象 this使用位置 this在实例初始化相关的代码块和构造器中:表示正在创建的那个实例对象,即正在new谁,this就代表谁this在非静态实例方法中:表示调用该方法的对象,即谁在调…...
MySQL 共享锁 (lock in share mode),排他锁 (for update)
共享锁 (lock in share mode) 简介 允许不同事务之间加共享锁读取,但不允许其它事务修改或者加入排他锁 如果有修改必须等待一个事务提交完成,才可以执行,容易出现死锁 共享锁事务之间的读取 session1: start transaction; select * from…...
类与对象(下)
文章目录类与对象(下)1. 再谈构造函数1.1 构造函数体赋值1.2 初始化列表特点推荐坑1.3 explicit关键字2. static成员2.1 概念面试题解法1解法2解法3(重要)2.2 特性问题3. 友元3.1 友元函数说明3.2 友元类4. 内部类4.14.25. 匿名对象6.拷贝对象时的一些编译器优化总结类与对象(下…...
feign技巧 - form方式传值
feign技巧 - form方式传值。 0. 文章目录1. 前言2. 调用样例3. 原理解析3.1 feign端序列化参数3.2 SpringMVC服务端解析参数3.3 补充 - 继承关系不会被传递的原因3.4 补充 - 不能使用GET。4. 总结1. 前言 直接正题。 如何使用feign进行fom表单方式的请求调用,以及其…...
MATLAB | 情人节来绘制更立体的玫瑰花吧
又是一年情人节,今年带来一款更有立体感的玫瑰: 曲面的函数表达式来自: http://www.bugman123.com/Math/index.html 这个网站,上面还有很多其他帅气的玩意。 基础绘制 xlinspace(0,1,300); thetalinspace(-2*pi,15*pi,300); [x,theta]meshg…...
【Python表白代码】 2.14“Valentine‘s Day”“没别的意思 就是借着特殊日子说声喜欢你”你在哪儿?我去见你~(各种玫瑰源码合集)
导语 Valentines Day Every man is a poet when he is in love 所有文章完整的素材源码都在👇👇 粉丝白嫖源码福利,请移步至CSDN社区或文末公众hao即可免费。 哈喽!我是你们的木木子吖~ 情人节又到了,礼物备好了没&am…...
压力应变电桥信号隔离放大变送器差分输入0-±10mV/0-±20mV转0-20mA/0-10v
概述:DIN11 IPO 压力应变桥信号处理系列隔离放大器是一种将差分输入信号隔离放大、转换成按比例输出的直流信号导轨安装变送模块。产品广泛应用在电力、远程监控、仪器仪表、医疗设备、工业自控等行业。此系列模块内部嵌入了一个高效微功率的电源,向输入…...
Linux系统之部署个人导航页
Linux系统之部署个人导航页 一、本次导航页工具介绍二、检查本地系统环境1.检查系统版本2.检查系统内核版本三、下载导航页软件包1.创建下载目录2.下载导航页软件包四、部署前环境准备工作1.安装python32.安装pipenv3.创建虚拟环境①创建环境②修改base.py文件③修改settings.p…...
四、Windows 平台安装 MongoDB
MongoDB 提供 64 位系统的预编译二进制包 我们可以从 MongoDB 官网下载安装 MongoDB 预编译二进制包下载地址:Try MongoDB Atlas Products | MongoDB 在 MongoDB 2.2 版本后已经不再支持 Windows XP 系统 最新版本也已经没有了 32 位系统的安装文件 MongoDB for W…...
浅谈应用安全测试工具
正确的应用程序安全测试工具可以改善企业安全态势和开发工作流程。如今,应用程序安全从一开始就内置在整个软件生命周期中,即使是具有成熟开发实践的组织也需要自动化工具来在复杂、快速变化的环境中成功地保护他们的软件。以下比较了三个广泛使用的应用…...
四类(七种)排序算法总结
一、插入排序 基本思想: 每次将一个待排序的对象,按其关键码大小,插入到前面已经排好序的一组对象的适当位置上,直到对象全部插入为止。即边插入边排序,保证子序列中随时都是排好序的。 基本操作——有序插入ÿ…...
[oeasy]python0083_十进制数如何存入计算机_八卦纪事_BCD编码_Binary_Coded_Decimal
编码进化 回忆上次内容 上次 研究了 视频终端的 演化 从VT05 到 VT100从 黑底绿字 到 RGB 24位真彩色形成了 VT100选项 从而 将颜色 数字化 了 生活中我们更常用 10个数字 但是 计算机中 用二进制 日常计数的十进制数 是如何存储进计算机的呢?🤔 从10进制到2进…...
理解框架的编译时与运行时
首先我们需要先理解一下什么事编译时和运行时 在语言层面,先来聊一下前端开发者最常遇见的两种语言JavaScript和Java Java的代码就是被编译为.class 文件才能运行,这个编译过程就是编译时,运行 .class 文件就是运行时我们在浏览器直接输入一…...
推挽电路---采用二极管消除交越失真----克服交越失真的互补推挽输出电路图
交越失真产生的原因及消除方法 由于晶体管的门限电压不为零,比如一般的硅三极管,NPN型在0.7V以上才导通,这样在00.7就存在死区,不能完全模拟出输入信号波形,PNP型小于-0.7V才导通,比如当输入的交流的正弦波…...
day11_面向对象
今日内容 零、 复习昨日 一、一日一题(数组,OOP) 二、面向对象练习(方法参数返回值) 三、局部变量&成员变量 四、this关键字 五、构造方法 六、重载 七、封装 小破站同步上课视频: https://space.bilibili.com/402601570/channel/collectiondetail?…...
大数据处理学习笔记1.1 搭建Scala开发环境
文章目录零、本讲学习目标一、Scala简介(一)Scala概述(二)函数式编程(三)Scala特性1、一切都是对象2、一切都是函数3、一切都是表达式(四)在线运行Scala二、选择Scala版本三、Window…...
VSCODE C++ 调用matplotlibcpp画图
使用VSCODE编写C程序,想在调试过程中看中间数据的波形,于是找到了python的matplotlibcpp库,参考文章链接是:https://blog.csdn.net/weixin_43769166/article/details/118365416;按照他的步骤配置好之后,跳出…...
面对“开门红”,跨境支付如何寻求新增长曲线?
易观:2022年是第三方支付行业洗牌加剧的一年,在部分机构选择退出的过程中,也有机构开始瞄准跨境业务,成为了支付机构转型的重要方向之一。跨境支付是指两个或及其以上的国家或地区进行国际贸易、国际投资或其他经济活动࿰…...
MySQL入门篇-MySQL MHA高可用实战
MHA简介 MHA(Master High Availability)目前在MySQL高可用方面是一个相对成熟的解决方案,它由日本DeNA公司的youshimaton(现就职于Facebook公司)开发,是一套优秀的作为MySQL高可用性环境下故障切换和主从提…...
C语言文件操作
目录1.文件指针2.文件的打开和关闭3.文件的读写3.1文件的顺序读写fgetc和fputcfgets和fputsfscanf和fprintffread和fwrite3.2文件的随机读写fseekftellrewind4.文本文件和二进制文件5.文件读取结束的判定6.文件缓冲区1.文件指针 在文件操作中,一个关键的概念是文件…...
Flink中核心重点总结
目录 1. 算子链 1.1. 一对一(One-to-one, forwarding) 1.2. 重分区(Redistributing) 1.3. 为什么有算子链 2. 物理分区(Physical Partitioning) 2.1. 什么是分区 2.2. 随机分区ÿ…...
gismo中NURBS的相关函数的使用---待完善
文章目录 前言一、B样条的求值1.1 节点向量的生成1.2 基函数的调用1.3 函数里面的T指的是系数类型二、以等几何两个单元12个控制点为例输出的控制点坐标有误1.4二、#pic_center <table><tr><td bgcolor=PowderBlue>二维数2.12.22.32.4三、3.13.23.33.4四、4.…...
5.数据共享与持久化
数据共享与持久化 在容器中管理数据主要有两种方式: 数据卷(Data Volumes)挂载主机目录 (Bind mounts) 数据卷 数据卷是一个可供一个或多个容器使用的特殊目录,它绕过UFS,可以提供很多有用的特性: 数据…...
RabbitMQ-客户端源码之AMQCommand
AMQCommand不是直接包含Method等成员变量的,而是通过CommandAssembler又做了一次封装。 接下来先看下CommandAssembler类。此类中有这些成员变量: /** Current state, used to decide how to handle each incoming frame. */ private enum CAState {EXP…...
linux设置登录失败处理功能(密码错误次数限制、pam_tally2.so模块)和操作超时退出功能(/etc/profile)
一、登录失败处理功能策略 1、登录失败处理功能策略(服务器终端) (1)编辑系统/etc/pam.d/system-auth 文件,在 auth 字段所在的那一部分添加如下pam_tally2.so模块的策略参数: auth required pam_tally2…...
Centos7上Docker安装
文章目录1.Docker常识2.安装Docker1.卸载旧版本Docker2.安装Docker3.启动Docker4.配置镜像加速前天开学啦~所以可以回来继续卷了哈哈哈,放假在家效率不高,在学校事情也少点(^_−)☆昨天和今天学了学Docker相关的知识,也算是简单了解了下&…...
新瑞鹏“狂飙”,宠物医疗是门好生意吗?
宠物看病比人还贵,正在让不少年轻一族陷入尴尬境地。在知乎上,有个高赞提问叫“你愿意花光积蓄,给宠物治病吗”,这个在老一辈人看来不可思议的魔幻选择,真实地发生在当下的年轻人身上。提问底下,有人表示自…...
网站运营暂停/seo技术建站
转载于:https://www.cnblogs.com/pubgoso/p/10759712.html...
wordpress 安装百度统计/seo
2010-11-04 12:18:11| 分类: iOS 应用开发|字号 订阅 neogui2008-09-01 15:57Q: 如何在XCode中使用gcc编译生成的.a库文件?1. 把你的.a文件添加到^projectName下的任意一個組里(例如默認的Classes組)。2. 找到Target > ^targe…...
石家庄网站建设机构/好用的磁力搜索引擎
四大函数类型一. 局部和全局变量二. 引用三. 匿名函数四. 递归前言作者:神的孩子都在跳舞 关注我的csdn博客,更多python知识还在更新 一. 局部和全局变量 局部变量 (1)含义:就是在函数内部定义的变量(作用…...
郑州做网站需要多少钱/西安网站关键词推广
[编程资料]C语言库函数大全及应用实例十一函数名: setbkcolor 功 能: 用调色板设置当前背景颜色 用 法: void far setbkcolor(int color); 程序例: <?xml:namespace prefix o ns "urn:schemas-microsoft-com:office:office" />#i nclude &#x…...
书法网站开发的前景/线上营销策略都有哪些
对于鞋服行业的零售分销企业,大多数是多级组织架构的,如下图所示: 如何处理每个组织内部的业务以及和其它组织间的业务,是鞋服行业软件好坏的一个关键指标. 以上图为例,我们来讨论一下多级组织间的软件业务流程。 图中表示的是&a…...
济宁网站运营/网页模板网站
“Bug总归会有解决的那一天,但是女生真的搞不定啊!” 每到5.20,怎么讨女友欢心就成了老大难的问题。也许是和代码相处太久,很多程序员常常调侃自己已经丧失了哄女孩的能力。 为了表达爱意,程序员们使尽浑身解数&#…...