C++核心编程之内存分区模型,引用,函数提高

1,类型分区模型

c++程序在执行中,将内存大方向划分为4个区域

1,代码区:存放函数体的二进制代码,由操作系统进行管理的

2,全局区:存放全局变量和静态变量以及常量

3,栈区:由编译器自动分配释放,存放函数的参数值,局部变量等

4,堆区:由程序员分配和释放,若程序员不释放,程序结束时由操作系统回收

内存四区的意义:

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

1.1  程序运行前

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

代码区:

存放CPU执行的机器指令

代码区是共享的,共享的目的是对于频繁被执行的程序,只需要在内存中有一份代码即可

代码区是只读的,使其只读的原因是防止程序意外地修改了它的指令

全局区:

全局变量和静态变量存放于此

全局区还包含了常量区,字符串常量和其他常量也存放于此

该区域的数据在程序结束后由操作系统操作

代码展示:

#include<iostream>
using namespace std;//全局变量
int g_a = 10;
int g_b = 10;int main()
{//全局区//全局变量,静态变量,常量//创建普通局部变量int a = 10;int b = 10;cout << "局部变量a的地址:" << &a << endl;cout << "局部变量b的地址:" << &b << endl;cout << endl;cout << "全局变量g_a的地址:" << &g_a << endl;cout << "全局变量g_b的地址:" << &g_b << endl;cout << endl;//静态变量  在普通变量前加static,属于静态变量static int s_a = 10;static int s_b = 10;cout << "静态变量s_a的地址:" << &s_a << endl;cout << "静态变量s_b的地址:" << &s_b << endl;cout << endl;//常量//字符串常量cout << "字符串常量的地址为:" << &"hello world" << endl;cout << endl;//const修饰的变量//const修饰的全局变量const int c_g_a = 10;const int c_g_b = 10;cout << "全局常量 c_g_a的地址:" << &c_g_a << endl;cout << "全局常量 c_g_b的地址:" << &c_g_b << endl;cout << endl;//const修饰的局部变量const int c_l_a = 10;const int c_l_b = 10;cout << "全局常量 c_g_a的地址:" << &c_l_a << endl;cout << "全局常量 c_g_b的地址:" << &c_l_b << endl;cout << endl;system("pause");return 0;
}


总结:

c++中程序运行前分为全局区和代码区

代码区的特点是共享和只读

全局区中存放全局变量,静态变量,常量

常量区中存放const修饰的全局变量和字符串变量 

1.2  程序运行后

栈区:由编译器自动分配释放,存放函数的参数值,局部变量等

注意:不要返回局部变量的地址,栈区开辟的数据由编译器自动释放

int* func()
{//利用new关键字 可以将数据开辟到堆区//指针,本质也是局部变量,放在栈区,指针保存的数据是放在栈区int* a = new int(10);return a;
}
int main()
{//在堆区开辟数据int* p = func();cout << "第一个:" << *p << endl;//每一次都会保存正确的数据cout << "第二个:" << *p << endl;cout << "第二个:" << *p << endl;cout << "第二个:" << *p << endl;cout << "第二个:" << *p << endl;cout << "第二个:" << *p << endl;cout << "第二个:" << *p << endl;system("pause");return 0;
}

堆区:

由程序员分配释放,若 程序员不释放,程序结束时由操作系统释放

在C++中主要利用new在堆区开辟内存

示例:

int* func()
{int* a = new int(10);return a;
}
int main()
{int* p = func();cout << "第一个:" << *p << endl;//每一次都会保存正确的数据cout << "第二个:" << *p << endl;cout << "第二个:" << *p << endl;cout << "第二个:" << *p << endl;cout << "第二个:" << *p << endl;cout << "第二个:" << *p << endl;cout << "第二个:" << *p << endl;system("pause");return 0;
}

 

1.3  new操作符

C++中利用new操作符在堆区开辟数据

堆区开辟的数据,由程序员手动开辟,释放利用操作符delete

语法: new  数据类型

利用new创建的数据,会返回该数据对应的类型的指针

示例1:基本语法:

#include<iostream>
using namespace std;
//1,new的基本语法
int* func()
{//在堆区创建整型数据//new返回是 该数据类型的指针int* a = new int(10);return a;
}int main()
{int* p = func();cout << *p << endl;cout << *p << endl;cout << *p << endl;//delete p;//堆区的数据 由程序员管理开辟,程序员管理释放//如果向释放堆区的数据,利用关键字 deletecout << *p << endl;system("pause");return 0;
}

 

示例2:开辟数组 

//2,开辟数组
int main()
{int* arr = new int[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;//释放数组 delete后加[]//int* arr = new int[10];/*for (int i = 0; i < 10; i++)//释放后不能再次使用{arr[i] = i + 100;}for (int i = 0; i < 10; i++){cout << arr[i] << endl;}*/system("pause");return 0;
}

 

2,引用

2.1 引用的基本使用

作用:给变量起别名

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

示例: 

#include<iostream>
using namespace std;
int main()
{//引用的基本语法//数据类型  &别名 = 原名int a = 10;//创建引用int& b = a;cout << "a=" << a << endl;cout << "b=" << b << endl;b = 100;cout << "a=" << a << endl;cout << "b=" << b << endl;system("pause");return 0;
}

 

2.2 引用的注意事项

引用必须初始化

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

int main()
{int a = 10;int b = 10;//int& c;//报错,引用必须初始化int& c=a;//一旦初始化后,就不可以更改c = b;//这是赋值操作,不是更改引用cout << "a=" << a << endl;cout << "b=" << b << endl;cout << "c=" << c << endl;system("pause");return 0;
}

2.3 引用做函数参数

作用:函数传参是,可以利用引用的技术让形参修饰实参

优点:可以简化指针修饰实参

示例:

//引用做函数参数
//1,值传递
void Swap01(int a,int b)
{int temp = a;a = b;b = temp;cout << "a= " << a << endl;cout << "b= " << b << endl;cout << endl;
}
//2,地址传递
void Swap02(int* a, int* b)
{int temp = *a;*a = *b;*b = temp;cout << "a= " << *a << endl;cout << "b= " << *b << endl;cout << endl;
}//3,引用传递
void Swap03(int& a, int& b)
{int temp = a;a = b;b = temp;cout << "a= " << a << endl;cout << "b= " << b << endl;cout << endl;
}
int main()
{Swap01(10,20);//值传递,形参不会修饰实参int a = 30;int b = 40;cout << "a= " << a << endl;cout << "b= " << b << endl;cout << endl;Swap02(&a,&b);//地址传递,形参会修饰实参cout << "a= " << a << endl;cout << "b= " << b << endl;cout << endl;a = 50;b = 60;Swap03(a, b);//引用传递,形参会修饰实参cout << "a= " << a << endl;cout << "b= " << b << endl;cout << endl;system("pause");return 0;
}

总结:通过引用参数产生的效果同按地址传递是一样的。

           引用的语法更清楚 

2.4 引用做函数返回值

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

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

用法:函数调用作为左值

示例1:

1,不要返回局部变量的引用

int& test01()
{int a = 10; //局部变量放在四区中的栈区return a;
}int main()
{int &ref = test01();cout << "ref= " << ref << endl;//第一次结果正确,是因为编译器做了保留cout << "ref= " << ref << endl;//第二次结果错误,是因为a的内存已经释放system("pause");return 0;
}

示例二: 

//函数的调用可以作为左值
int& test02()
{static int a = 10; //静态变量存放在全局区,全局区上的数据在程序结束后系统释放return a;
}int main()
{int& ref = test02();cout << "ref= " << ref << endl;cout << "ref= " << ref << endl;test02() = 1000;//如果函数的返回值是引用,这个函数调用可以作为左值cout << "ref= " << ref << endl;cout << "ref= " << ref << endl;system("pause");return 0;
}

2.5 引用的本质

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

示例:

//引用的本质
//发现是引用,转换为int* const ref = &a;
void func(int& ref)
{ref = 100;//ref是引用,转换为*ref = 100;
}int main()
{//自动转化为int* const ref = &a;指针常量是指针指向不可改,也说明为什么引用不可以更改int a = 10;int& ref = a;ref = 20;//内部发现ref是引用,自动帮我们转换为*ref=20;cout << "a= " << a << endl;cout << "ref= " << ref << endl;func(a);cout << "a= " << a << endl;cout << "ref= " << ref << endl;system("pause");return 0;
}

结论:C++推荐引用技术,因为语法方便,引用本质是常量指针 

2.6 常量引用

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

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

示例:

//引用使用的场景,通常用来修饰形参
void showValue(const int& v)
{//v += 10;cout <<"v= "<< v << endl;
}
int main()
{//int& ref = 10;//引用本身需要一个合法的内存空间,因此这行错误//加入const就可以了,编译器做了优化代码,int temo = 10;const int& ref = temp;const int& ref = 10;cout << "ref= "<<ref << endl;//ref=100;//加入const后不可以修改变量int a = 10;//函数中利用常量引用防止误操作修改实参showValue(a);system("pause");return 0;
}

3,函数提高 

3.1 函数默认参数

在C++中,函数的形参列表中的形参是由默认值的。

语法:返回值类型  函数名 (参数 = 默认值){}

示例1:

#include<iostream>
using namespace std;
int func1(int a, int b, int c)
{return a + b + c;
}//如果我们积极传入数据,就用自己的数据,如果没有,那就用默认值
//b未传入数据,则使用默认值
int func2(int a, int b = 20, int c = 30)
{return a + b + c;
}//都传入了数据,那就用自己的数据
int func3(int a, int b, int c)
{return a + b + c;
}int main()
{cout << "func1()的值" << endl;cout << func1(10, 20, 30) << endl;cout << endl;cout << "func2()的值" << endl;cout << func2(10, 30) << endl;cout << endl;cout << "func3()的值" << endl;cout << func1(30, 40, 50) << endl;cout << endl;system("pause");return 0;

示例2:

 

//注意事项:
//1,如果某个位置已经有了默认参数,那么从那个位置往后,从左到右必须都有默认值
//int func1(int a=10, int b, int c,int d)//错误
//{
//	return a + b + c;
//}//2,如果函数声明由默认参数,函数实现就不能由默认参数
//int func2(int a=10, int b=10);
//声明和实现都能有一个默认参数
int func2(int a=10, int b=20)
{return a + b;
}int main()
{cout << func2(10) << endl;return 0;
}

3.2函数占位参数

C++中函数的形参列表里可以有占位参数,用来做占位,调用函数时必须填补该位置

语法:返回值类型 函数名  (函数类型){ }

在现阶段函数的占位参数存在意义不大,但是后面的课程中会用到该技术

示例:

//函数占位参数,占位参数也可以有默认参数
void func(int a, int)
{cout << "this is func" << endl;
}
int main()
{func(10, 10);//占位参数必须填补system("pause");}

3.3 函数重载

void func()
{cout << "func的调用" << endl;
}void func(int a)
{cout << "func的调用" << endl;
}void func(double a)
{cout << "func的调用" << endl;
}//函数返回值不能作为函数重载条件
//int func(double a,int b)
//{
//	cout << " func(double a,int b)" << endl;
//}int main()
{//func()func(10);func(3.14);
}

作用:函数名可以相同,提高复用性

3.3.1函数重载满足条件:

1,同一个作用域下

2,函数名相同

3,函数参数类型不同或者个数不同或者顺序不同

注意:函数的返回值不可以作为函数重载的条件

void func()
{cout << "func的调用" << endl;
}void func(int a)
{cout << "func的调用" << endl;
}void func(double a)
{cout << "func的调用" << endl;
}//函数返回值不能作为函数重载条件
//int func(double a,int b)
//{
//	cout << " func(double a,int b)" << endl;
//}int main()
{//func()func(10);func(3.14);
}

3.3.2  函数重载注意事项

1,引用作为重载条件

2,函数重载碰到函数默认条件

示例:

// 函数重载注意事项
//1,引用作为重载条件
void func(int& a)
{cout << "func(int &a)的调用" << endl;
}void func(const int& a)
{cout << "func(int &a)的调用" << endl;
}
//2,函数重载碰到函数默认条件
void func2(int a, int b = 10)
{cout << "func2(int a,int b = 10)调用" << endl;
}void func2(int a)
{cout << "func2(int a)调用" << endl;
}int main()
{int a = 10;//func2(a);//调用无const//func2(10);//调用有const//func2(10);//碰到默认参数产生歧义,需要避免system("pause");return 0;
}

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

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

相关文章

Spring框架的优点

Spring框架是一个开放源代码的J2EE应用程序框架&#xff0c;是针对bean的生命周期进行管理的轻量级容器。 Spring解决了开发者在J2EE开发中遇到的许多常见的问题&#xff0c;提供了功能强大的IOC、AOP及Web MVC等功能。 轻量级&#xff1a;相对于EJB框架而言。 Spring 体系结…

Windows安装SSH教程

Windows安装SSH教程 一、SSH1.SSH简介2.SSH功能3.SSH验证3.1 第一种级别&#xff08;基于口令的安全验证&#xff09;3.2 第二种级别&#xff08;基于密匙的安全验证&#xff09; 4.SSH层次4.1 传输层协议 [SSH-TRANS]4.2 用户认证协议 [SSH-USERAUTH]4.3 连接协议 [SSH-CONNEC…

node-day3-es6模块化+webpack

模块化 一、模块化分类 回顾node.js模块化&#xff1a; node.js遵循了CommonJS的模块化规范【见下文】&#xff0c;其中&#xff1a; 1.导入其它模块使用require()方法 2.模块对外共享成员使用module.exports对象 模块化的好处&#xff1a; 大家都遵守同样的模块化规范写代…

【学习笔记】开源计算机视觉库OPENCV学习方案

本文中&#xff0c;我们试图提供一些学习OpenCV的详细和实用资源&#xff0c;这些资源包括基础知识、进阶技巧以及实践项目&#xff0c;旨在帮助初学者和进阶学习者更好地掌握和使用OpenCV库。 一、学习资源 官方文档&#xff1a;OpenCV的官方文档是学习OpenCV的最佳起点。它包…

向量数据库Chroma教程

引言 随着大模型的崛起,数据的海洋愈发浩渺无垠。受限于token的数量,无数的开发者们如同勇敢的航海家,开始在茫茫数据之海中探寻新的路径。他们选择了将浩如烟海的知识、新闻、文献、语料等,通过嵌入算法(embedding)的神秘力量,转化为向量数据,存储在神秘的Chroma向量…

飞书云文档API操作详细介绍

1.场景分析 公司内部很多文档都是由多人进行维护的&#xff0c;随时发生变更&#xff0c;因此在利用这些数据的时候就需要直接读取云文档的数据&#xff0c;从而执行下一步动作。团队云文档api执行权限一般需要管理员审核才能使用。如果你就是管理员&#xff0c;那么恭喜你&am…

【DIY】钱包的“电子卫士”的制作

一、工作原理 钱包的“电子卫士”电路如图1所示&#xff0c;其核心元件是微型蜂鸣器专用音响集成电路A&#xff0c;它与压电陶瓷蜂鸣片B、电池G等组成了一个体积小巧、发声响亮的简易蜂鸣器。 平时&#xff0c;钱包通过尼龙线与插头XP相接&#xff0c;而XP插入插孔XS内&#x…

AndroidUI--setContentView

我们的Activity通常继承自Activity或者AppCompatActivity&#xff0c;这两个setContentView流程是不同的 一、继承自Activity 1、Activity.setContentView Activity中setContentVIew调用了getWindow().setContentView(view, params); getWindow返回的是mWindow&#xff0c;mWi…

RedisDesktopManager连接Ubuntu的Redis失败解决办法

配置redis 1.设置redis在后台服务&#xff0c;修改配置文件 默认情况下是 no ,修改为yes&#xff0c;可以后台服务 2、设置redis端口&#xff0c;默认端口是6379&#xff0c;可以根据自己的需要&#xff0c;找到/et/redis/redis.conf文件, 修改port 3、设置密码 配置文件中…

ubuntu20.04“E: 软件包 vim 没有可安装候选”“/etc/apt/sources.list:7 中被配置了多次”解决方法

问题一&#xff1a;ubuntu20.04安装vim时提示“E: 软件包 vim 没有可安装候选” **解决&#xff1a;**更换下载&#xff0c;比如我原先使用的是清华源&#xff0c;后切换成阿里云源&#xff0c;ubuntu直接在“软件和更新”切换 问题一解决。 问题二&#xff1a;ubuntu20.04提…

JavaEE+springboot教学仪器设备管理系统o9b00-springmvc

本文旨在设计一款基于Java技术的教学仪器设备销售网站&#xff0c;以提高网站性能、功能完善、用户体验等方面的优势&#xff0c;解决现有教学仪器设备销售网站的问题&#xff0c;并为广大教育工作者和学生提供便捷的教学仪器设备销售渠道。本文首先介绍了Java技术的相关基础知…

华为昇腾系列——入门学习

概述 昇腾&#xff08;Ascend&#xff09;是华为推出的人工智能处理器品牌&#xff0c;其系列产品包括昇腾910和昇腾310芯片等。 生态情况 众所周知&#xff0c;华为昇腾存在的意义就是替代英伟达的GPU。从事AI开发的小伙伴&#xff0c;应该明白这个替代&#xff0c;不仅仅是…

【自动驾驶坐标系基础】Frenet坐标系和Cartesian坐标系的相互转换

Frenet坐标系和Cartesian坐标系的相互转换 2023.12.12 1 变量含义 Frenet和Cartesian相互转换即 [ s , s ˙ , s , d , d ˙ , d ] ↔ [ X , θ x , κ x , v x , a x ] [s,\dot{s},\ddot{s},d,\dot{d},\ddot{d}] \leftrightarrow[\boldsymbol{X},\theta_x,\kappa_x,v_x,a_…

【Unity开发】【VR】PICO项目在运行编辑器时无法正常显示游戏场景

【背景】 做了一个PICO项目&#xff0c;真机在手边时开发后用PC的Preview模式直接调试&#xff0c;真机不在手边时希望用VRTK的Simulation Rig&#xff0c;用键鼠模拟控制器输入进行快速调试。但是发现Simulation Rig状态下运行后&#xff0c;游戏场景变得很怪&#xff0c;很多…

RLT8762D---添加service

0 Preface/Foreword 1 系统初始化LE profile过程 正常开机流程中&#xff0c;gap初始化完成之后&#xff0c;才能进行LE profile初始化。 1.1 添加服务 1.1.1 注册支持服务个数(GATT Server) 函数&#xff1a; server_init 目的&#xff1a;set the number of services th…

MySql缓冲池命中率

缓冲池 大小查看 show variables like innodb_buffer_pool_size; 太小的innodb_buffer_pool_size是不利于性能的提升 命中率查看 一 、 通过以下命令查看相关数据&#xff1a; show global status like Innodb_buffer_pool_read%;结果如下&#xff1a; 命中率公式&#xff1…

Zabbix监控容器MongoDB,报错:Unknown metric mongodb.server.status

在Zabbix中配置监控MongoDB容器时&#xff0c;如果遇到Unknown metric mongodb.server.status这样的错误&#xff0c;通常意味着Zabbix Agent尝试从MongoDB获取某个预定义的性能指标&#xff08;例如mongodb.server.status&#xff09;&#xff0c;但是未能成功识别或解析该指标…

GPT4+Python近红外光谱数据分析及机器学习与深度学习建模教程

原文链接&#xff1a;GPT4Python近红外光谱数据分析及机器学习与深度学习建模教程 第一&#xff1a;GPT4 1、ChatGPT&#xff08;GPT-1、GPT-2、GPT-3、GPT-3.5、GPT-4模型的演变&#xff09; 2、ChatGPT对话初体验 3、GPT-4与GPT-3.5的区别&#xff0c;以及与国内大语言模…

微信小程序开发系列(十六)·事件传参·data-*自定义数据

事件传参&#xff1a;在触发事件时,将一些数据作为参数传递给事件处理函数的过程,就是事件传参。 在微信小程序中,我们经常会在组件上添加一些自定义数据,然后在事件处理函数中获取这些自定义数据,从而完成业务逻辑的开发。 在组件上通过data-"的方式定义需要传递的数据,其…

Android14之解决编译报错:bazel: no such file or directory(一百八十九)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 优质专栏&#xff1a;多媒…