c++ 内存分析模型、引用

 一、内存模型分区

内存四区的意义:

不同区域存放的数据,赋予不同的生命周期,给我们更大的灵活编程

(一)程序运行前

在程序编译后,生成了exe可执行程序,未执行程序前分为两个区域

代码区:

  • 存放cpu执行的机器指令(代码的2进制)
  • 代码区是共享的,共享的目的是对于频繁执行的程序,只需要在内存中有一份代码即可
  • 代码区是只读的,使其只读的原因是防止程序意外的修改了其它指令

全局区:

  • 全局变量和静态变量存放在此
  • 全局区还包含了常量区,字符串常量和其他常量也存放在此
  • 该区域的数据在程序结束后由操作系统释放

#include<iostream>
using namespace std;
int g_a = 10;
int g_b = 10;
//const修饰的全局变量,全局常量
int c_g_a = 10;
int c_g_b= 10;
int main()
{
//全局区
//全局变量、静态变量、常量//创建普通局部变量
int a = 10;
int b = 20;
cout << "局部变量a的地址为:" << (int)&a << endl;
cout << "局部变量a的地址为:" << (int)&b << endl;
cout << "全局变量g_a的地址为:" <<(int)&g_a << endl;
cout << "全局变量g_b的地址为:" <<(int)&g_b << endl;
//创建静态变量
static int s_c = 10;
static int s_d = 10;
cout << "静态变量s_c的地址为:" << (int)&s_c << endl;
cout << "静态变量s_d的地址为:" << (int)&s_d << endl;//常量
//字符串常量
cout<<"字符串常量的地址为:"<<(int) & "hello world"<<endl;
//const修饰的变量
//const 修饰的全局变量 
// const修饰的局部变量
const int c_l_a = 10;
const int c_l_b = 10;
cout << "const修饰的全局常量c_g_a的地址为:" << (int)&c_g_a << endl;
cout << "const修饰的全局常量c_g_b的地址为:" << (int)&c_g_b << endl;
cout << "const修饰的局部变量c_l_a的地址为:" << (int)&c_l_a << endl;
cout << "const修饰的局部变量c_l_b的地址为:" << (int)&c_l_b << endl;
system("pause");
return 0;}
#include <iostream>
using namespace std;
//栈区数据的注意事项 ---不要返回局部变量的地址
//栈区的数据由编译器管理开辟和释放int* func(int b) {//形参数据也会放在栈区b = 200;int a = 10;//局部变量 存放在栈区,栈区的数据在函数执行完后自动释放return  & a;//返回局部变量的地址}
int main() {//接受func函数的返回值int *p = func(1);cout << "p = " << *p << endl;cout << "p = " << *p << endl;system("pause");return 0;
}

(二)程序运行后

栈区:

  • 由编译器自动分配释放,存放函数的参数值,局部变量等
  • 注意事项:不要返回局部变量的地址,栈区开辟的数据由编译器自动释放
#include <iostream>
using namespace std;
//栈区数据的注意事项 ---不要返回局部变量的地址
//栈区的数据由编译器管理开辟和释放int* func(int b) {//形参数据也会放在栈区b = 200;int a = 10;//局部变量 存放在栈区,栈区的数据在函数执行完后自动释放return  & a;//返回局部变量的地址}
int main() {//接受func函数的返回值int *p = func(1);cout << "p = " << *p << endl;cout << "p = " << *p << endl;system("pause");return 0;
}

堆区:

  • 由程序员分配释放,若程序员不释放,程序结束时由操作系统回收
  • 在c++中主要利用new在堆区开辟内存
#include<iostream>
using namespace std;int * func() {//利用new关键字 可以将数据开辟到堆区//指针 本质也是局部变量,放在栈上,指针保存的数据是放在堆区int * p = new int(10);return p;}int main() {//在堆区开辟数据int *p=func();cout << "p=" << *p << endl;system("pause");return 0;
}

 

(三)new操作符

  • c++中利用new操作符在堆区开辟数据
  • 堆区开辟的数据,由程序员手动开辟,手动释放,释放利用操作符 delete
  • 语法: new 数据类型
  • 利用new创建的数据,会返回该数据对应的类型的指针

没有进行delete清除时

 使用delete进行清除后

#include <iostream>
using namespace std;
//1、new的基本语法
int* func() {//在堆区创建整形数据//new返回的是一个该数据类型的指针int *p = new int(10);return p;}
//2、在堆区利用new开辟数组
void test02() {//创建10整型数据的数组,在堆区
int * arr=	new int[10];//10代表数组有10个元素
for (int i = 0; i < 10; i++)
{arr[i] = i + 100;
}
for (int i = 0; i < 10; i++) {cout << arr[i] << endl;
}
//释放数组的内存空间
delete[] arr; //释放数组需要加[]
}
void test01()
{int* p = func();cout << *p << endl;cout << *p << endl;cout << *p << endl;//堆区的数据 由程序员管理开辟,程序员管理释放//利用关键字delete释放堆区数据delete p;}
int main()
{test01();test02();system("pause");return 0;}

二、引用

(一)引用的基本使用

作用:给变量起别名

语法:数据类型 &别名=原名

#include<iostream>
using namespace std;int main() {//引用的基本语法//数据类型 &别名 =原名int a = 10;int& b = a; //b是a的引用cout << "a=" << a << endl;cout << "b=" << b << endl;b = 20; //修改b的值,a也会跟着变化cout << "a=" << a << endl;cout << "b=" << b << endl;system("pause");return 0;}

(二)引用的注意事项

  • 引用必须初始化
  • 引用在初始化后,不可以改变

#include<iostream>
using namespace std;
int main()
{int a = 10;//1、引用必须初始化//int& b; //错误,必须要初始化int& b = a;//2、引用在初始化后,不可以改变int c = 20;b = c;//赋值操作而不是更改引用cout << "a=" << a << endl; //输出20cout << "b=" << b << endl; //输出20cout << "c=" << c << endl; //输出20//3、引用的本质是指针,因此可以直接操作指针指向的内存空间system("pause");return 0;}

(三)引用做函数参数

  • 作用:函数传递时,可以利用引用的技术让形参修饰实参
  • 优点:可以简化指针修改实参
#include <iostream>
using namespace std;
//交换函数//1.值传递
void mySwap01(int a,int b) {int temp = a;a = b;b = temp;
}
//2.地址传递
void mySwap02(int* a, int* b) {int temp = *a;*a = *b;*b = temp;
}
//3.引用传递
void mySwap03(int &a, int &b) {int temp = a;a =b;b = temp;
}int main() {int a = 10, b = 20;cout << "a = " << a << " b = " << b << endl;mySwap01(a, b);//值传递 形参不会修饰实参cout << "a = " << a << " b = " << b << endl;mySwap02(&a, &b);//地址传递 形参会修饰实参cout << "a = " << a << " b = " << b << endl;mySwap03(a, b);//引用传递 形参会修饰实参cout << "a = " << a << " b = " << b << endl;system("pause");return 0;
}

(四)引用做函数返回值

作用:引用是可以作为函数的返回值存在

注意:不要返回局部变脸引用

用法:函数调用作为左值

#include <iostream>
using namespace std;
//引用做函数的返回值//1.不要返回局部变量的引用
int& test01() {int a = 10;return a; //错误,局部变量的引用不能作为函数的返回值
}//2.函数的调用可以作为左值
int & test02() {static int a = 10;//静态变量(全局变量)return a;
}int main() {int & ref = test01();cout << ref << endl; //第一次结果正确,是因为编译器做了保留cout <<"ref="  << ref << endl;//第二次结果错误,是因为a的内存已经释放cout << ref << endl;cout << ref << endl;cout << ref << endl;cout << ref << endl;int &ref2 = test02();cout << ref2 << endl;cout << ref2 << endl;cout << ref2 << endl;test02() = 1000;//如果函数的返回值是引用,这个函数调用可以作为左值cout << "ref2=" << ref2 << endl;cout << "ref2=" << ref2 << endl;cout << "ref2=" << ref2 << endl;system("pause");return 0;
}

(五)引用的本质

本质:引用的本质在c++内部实现是一个指针常量

#include <iostream>
using namespace std;
//发现是引用,转换为int * const ref=&a;
void func(int &ref) {ref = 100;//ref是引用,转换为 *ref=100}int main() {int a = 10;//自动转换为 int * const ref=&a; 指针常量是指针指向不可改,也说明了引用不可更改int &ref = a; ref = 20;//内部发现ref是引用,自动帮我们转换为:*ref=20;cout << "a=" << a << endl; //a=20cout << "ref=" << ref << endl;system("pause");return 0;
}

(六)常量引用

作用:常量引用主要用来修饰形参,防止误操作

在函数形参列表中,可以加const修饰形参,防止形参改变实参

不加const修饰 

#include <iostream>using namespace std;
//打印数据的函数
void showValue( int & val){val = 1000;cout << "value =" << val << endl;
}
int main() {//常量引用//使用场景 用来修饰形参,防止误操作int a = 10;//加上const之后 编译器将代码修改 int temp=10;const int &ref=temp;const int& ref = 10;//引用必须引一块合法的内存空间//ref = 20;//加入const之后变为只读,不可以修改cout << "ref =" << ref << endl;int b = 100;showValue(b);//调用函数传递引用system("pause");return 0;
}

加入const修饰

#include <iostream>using namespace std;
//打印数据的函数
void showValue(const int & val){//val = 1000; //加入const 后会报错 不能修改cout << "value =" << val << endl;
}
int main() {//常量引用//使用场景 用来修饰形参,防止误操作int a = 10;//加上const之后 编译器将代码修改 int temp=10;const int &ref=temp;const int& ref = 10;//引用必须引一块合法的内存空间//ref = 20;//加入const之后变为只读,不可以修改cout << "ref =" << ref << endl;int b = 100;showValue(b);//调用函数传递引用system("pause");return 0;
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

SpringMVC系列七: 手动实现SpringMVC底层机制-上

手动实现SpringMVC底层机制 博客的技术栈分析 &#x1f6e0;️具体实现细节总结 &#x1f41f;准备工作&#x1f34d;搭建SpringMVC底层机制开发环境 实现任务阶段一&#x1f34d;开发ZzwDispatcherServlet&#x1f966;说明: 编写ZzwDispatcherServlet充当原生的DispatcherSer…

码云建仓库

1.新建仓库 码云地址 打开 码云地址 &#xff0c;点击“”&#xff0c;新建仓库&#xff0c;添加仓库内容 &#xff0c;创建。 小提示&#xff1a;如果本地已有项目&#xff0c;就不要选初始化&#xff0c;设置模板&#xff0c;容易冲突。 2. 进入当前仓库页 小提示&#x…

【2024最新华为OD-C/D卷试题汇总】[支持在线评测] LYA的巡演(100分) - 三语言AC题解(Python/Java/Cpp)

&#x1f36d; 大家好这里是清隆学长 &#xff0c;一枚热爱算法的程序员 ✨ 本系列打算持续跟新华为OD-C/D卷的三语言AC题解 &#x1f4bb; ACM银牌&#x1f948;| 多次AK大厂笔试 &#xff5c; 编程一对一辅导 &#x1f44f; 感谢大家的订阅➕ 和 喜欢&#x1f497; &#x1f…

心明眼亮 洞悉万物

如何洞悉事物的本质呢&#xff1f; 阳明先生&#xff1a;世间之事&#xff0c;纷繁复杂&#xff0c;不可能一一研究得过来。 圣人只需要把内心的明镜擦亮&#xff0c;而无需担心外部的事事物物在镜子中如何映照。 —— 外界事物是无穷无尽的&#xff0c;永远探究不完&#xf…

30 - 每位经理的下属员工数量(高频 SQL 50 题基础版)

30 - 每位经理的下属员工数量 -- 根据reports_to &#xff0c;获取employee_id,即分组用e1.reports_to&#xff0c;查询用e2.employee_id,e2.nameselect e2.employee_id,e2.name ,count(e1.reports_to) reports_count,round(avg(e1.age),0) average_age from Employees e1 left…

【鸿蒙踩坑记录】解决:list组件滑动至左边或右边,回弹效果过大问题

一、问题描述 开发过程中使用List组件&#xff0c;当内容超过一屏时可出现滚动效果&#xff0c;此时按住内容迅速滑动至左边&#xff0c;或者滑动到右边&#xff0c;回弹效果过大 期望&#xff1a;滑动时&#xff0c;不要有那么大的回弹效果 二、目前效果 三、解决方法 3.1…

go语言day03

目录 一、 go语言的数据类型&#xff1a; 二、声明赋值的简写形式&#xff1a; ":" 1&#xff09;重复使用的编译错误 2&#xff09;在全局变量中使用 : 会报编译错误 三、变量规则&#xff1a; 0&#xff09;变量的命名规则&#xff1a; 1&#xff09;创建的局部…

丰臣秀吉-读书笔记六

登山的目标必然是山顶。但人生的乐趣和生息的快乐却不在山顶&#xff0c;相反可以说是在山中的逆境之处。当我们遇上峡谷、绝壁、溪流、断崖、雪崩之类的险路时&#xff0c;心里虽想着已经不行了等&#xff0c;却不甘就此罢手而不与面前的艰难险阻战斗。而当我们完美克服并跨越…

用 Rust 实现一个替代 WebSocket 的协议

很久之前我就对websocket颇有微词&#xff0c;它的确满足了很多情境下的需求&#xff0c;但是仍然有不少问题。对我来说&#xff0c;最大的一个问题是websocket的数据是明文传输的&#xff0c;这使得websocket的数据很容易遭到劫持和攻击。同时&#xff0c;WebSocket继承自HTTP…

Spark SQL 血缘解析方案

背景 项目背景建设数据中台,往往数据开发人员首先需要能够通过有效的途径检索到所需要的数据,然后根据检索的数据模型进行业务加工然后得到一些中间模型,最后再通过数据抽取工具或者OLAP分析工具直接将数据仓库中加工好的公共模型输出到应用层。这里我不在去介绍数据仓库为…

Mysql8死锁排查

Mysql8死锁排查 Mysql8 查询死锁的表 -- 查询死锁表select * from performance_schema.data_locks;-- 查询死锁等待时间select * from performance_schema.data_lock_waits;Mysql8之前的版本 查询死锁的表 -- 查询死锁表SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCKS;-- 查询…

Virtualbox主机和虚拟机之间文件夹共享及双向拷贝

在VirtualBox这样的虚拟化环境中&#xff0c;实现主机与虚拟机之间的文件夹共享与双向文件传输是一个常见的需求。下面&#xff0c;我们将详细讲解如何在VirtualBox中实现这一功能。 一、安装与准备 首先&#xff0c;确保你已经安装了VirtualBox&#xff0c;并在其上成功创建…

最大乘积和-第13届蓝桥杯省赛Python真题精选

[导读]&#xff1a;超平老师的Scratch蓝桥杯真题解读系列在推出之后&#xff0c;受到了广大老师和家长的好评&#xff0c;非常感谢各位的认可和厚爱。作为回馈&#xff0c;超平老师计划推出《Python蓝桥杯真题解析100讲》&#xff0c;这是解读系列的第85讲。 最大乘积和&#…

kafka进阶核心原理详解:案例解析(第11天)

系列文章目录 kafka高级&#xff08;重点&#xff09; kafka核心概念汇总 kafka的数据位移offset Kafka的基准/压力测试 Kafka的分片副本机制 kafka如何保证数据不丢失 kafka的消息存储及查询机制 生产者数据分发策略 消费者负载均衡机制 kafka的监控工具:kafka-eagle…

关于application/x-www-form-urlencoded跟application/json请求的区别

当你的java方法是这样定义的 PostMapping("/rePushMedicalRecord") public String rePushMedicalRecord(RequestParam("topicId") String topicId){ } 参数是RequestParam接收&#xff0c;则请求时需要用application/x-www-form-urlencoded请求 如果是R…

ArcGIS消除碎图斑

​ 点击下方全系列课程学习 点击学习—>ArcGIS全系列实战视频教程——9个单一课程组合系列直播回放 点击学习——>遥感影像综合处理4大遥感软件ArcGISENVIErdaseCognition 这次是上次 我们经常在相交、标识、更新等操作后或者是栅格转矢量可能存在很多的细碎图斑&#…

Golang三色标记法

简介 在JVM中&#xff0c;GC采用可达性分析法来判断对象是否死亡&#xff1b;在python虚拟机中&#xff0c;GC采用引用计数法加循环检测器来判断对象是否死亡&#xff0c;而在golang中&#xff0c;使用的是三色表记法来判断对象是否死亡。 什么是三色抽象 总所周知在GC时&am…

基于JSP技术的家用电器销售网站

开头语&#xff1a;你好呀&#xff0c;我是计算机学长猫哥&#xff01;如果有相关需求&#xff0c;文末可以找到我的联系方式。 开发语言&#xff1a;Java 数据库&#xff1a;MySQL 技术&#xff1a;JSPJava 工具&#xff1a;ECLIPSE、MySQL数据库管理工具、Tomcat 系统展…

【字符串 状态机动态规划】1320. 二指输入的的最小距离

本文涉及知识点 动态规划汇总 字符串 状态机动态规划 LeetCode1320. 二指输入的的最小距离 二指输入法定制键盘在 X-Y 平面上的布局如上图所示&#xff0c;其中每个大写英文字母都位于某个坐标处。 例如字母 A 位于坐标 (0,0)&#xff0c;字母 B 位于坐标 (0,1)&#xff0…

国企:2024年6月中国移动相关招聘信息

中国移动研究院: AI中心-大模型数据工程师 工作地点:北京市、西安市2 发布时间 :2024-06-18 学历要求:硕士研究生及以上 招聘人数:招聘若干人 专业要求 计算机、人工智能、软件工程、数学等相关专业 工作职责 1、负责处理和清洗大规模、多来源的数据集,保证数…