从0到1入门C++编程——03 内存分区、引用、函数高级应用

文章目录

  • 一、内存分区
  • 二、引用
  • 三、函数的高级应用
    • 1.默认参数
    • 2.占位参数
    • 3.函数重载

一、内存分区

C++程序在执行时,会将内存大致分为4个区,分别是代码区、全局区、栈区和堆区。
代码区用来存放函数体和二进制代码,由操作系统进行管理。
全局区用来存放全局变量、静态变量、字符串常量以及全局常量(const修饰的变量)。
栈区是由编译器自动分配和释放,用来存放函数的参数值、局部变量等。
堆区由程序员分配和释放,如果程序员分配了内存但没释放,程序结束时由操作系统回收,但是这种情况下有可能造成内存泄露。
内存分区可以使数据存放在不同的区域,并赋予其不同的生命周期,可以使得编程更加灵活。
程序编译后生成了可执行程序,未执行程序之前分为两个区域,代码区和全局区。代码区存放CPU执行的机器指令,代码区是共享的,共享的目的是对于频繁被执行的程序,只需要在内存中有一份代码即可;代码区是只读的,防止程序意外的被修改。全局区在程序结束后由操作系统释放。
由下图可以看到,全局变量的地址比局部变量的地址低。这是因为全局变量存放在全局区,局部变量存放在栈区。
在这里插入图片描述
注意局部常量和全局常量存放的位置是不一样的,局部常量仍然存放在栈区,而全局常量存放在全局区。
在栈区中需要注意,不要返回局部变量的地址! 因为局部变量存放在栈区,栈区的数据在函数执行完以后自动释放。
下面的例子可以看到,函数返回了局部变量的地址,在main函数中进行了接收,第一次解引用得到了正确的值是因为编译器做了保留,第二次打印数据就不再保留了,对返回的局部变量的地址操作是非法的。
在这里插入图片描述
对数组而言也是一样的,不能返回数组地址进行读写操作。
在这里插入图片描述
如果将局部变量变为静态变量,那么即使函数返回后,数据依然可以访问,因为变量的存放区域不再是栈区,而是全局区。
在这里插入图片描述
在C++中利用关键字new在堆区开辟内存,并以指针接收内存。 new什么类型的数据,就以什么类型的指针接收其地址,括号里面的值是给堆区开辟的内存初始化数值。程序员不释放,堆区中的数据一直存放到程序运行结束。
在这里插入图片描述
释放new开辟的内存使用关键字delete。
在堆区中开辟数组要用中括号,释放的时候要先在delete后加[]再加指针释放,释放单个数据的时候直接在delete后加指针即可。
在这里插入图片描述


二、引用

引用的作用是给变量起别名。引用必须初始化,且初始化以后不可以改变。
语法:数据类型 &别名 = 原名;
引用的本质在C++内部实现是一个指针常量,指针的指向不可修改,但是指针指向的值可以修改。

int a = 10;
int &b = a;  //相当于 int* const b = a;

C++ 推荐引用技术,语法方便,其涉及的指针操作都由编译器做了。
在给变量起别名的时候,数据类型要与原变量一致。
在这里插入图片描述
引用可以作为函数参数传递,其效果和指针一样,例如下面交换两个数的例子。
在这里插入图片描述
通过引用参数产生的效果同按地址传递时一样的,引用的语法更加清楚简单。
引用归根结底还是对地址的操作,下面是传递参数的三种不同方式。
指针方式是地址传递,因此在主函数和函数体中的变量地址是一样的。
在这里插入图片描述
引用也是地址传递,主函数和函数体中的变量地址一样。
在这里插入图片描述
值传递则与上面两种不一样,变量在主函数中的地址和函数体中的地址是不一样的,这也是为什么经过函数交换后实际的变量值没有发生交换,因为函数中操作的地址是在栈中另外开辟的。
在这里插入图片描述
引用可以作为函数的返回值,但是不要返回局部变量的引用!
返回局部变量的引用和返回局部变量的地址是一样的,函数返回后内存会被释放掉,再对该内存操作就是非法的,下面的打印第一次虽然是对的,但只是临时保存的。
在这里插入图片描述
函数的返回值是引用,函数调用可以作为左值!
函数调用作为左值相当于给返回的引用进行赋值操作,例子如下。
在这里插入图片描述
常量引用主要用来修饰形参,防止误操作改动实参数值。

int a = 10;
int &b = a;  //合法int a = 10;
int &b = 10;  //不合法int a = 10;
const int &b = 10;  //合法  相当于 int temp = 10; int &b = temp;

前面提到,引用其实是一个指针常量,因此当其作为函数形参传递的时候,如果在函数体中修改了形参,实参也会跟着变动,有时候为了防止函数中修改形参,要在引用前加上const。
可以看到,如果引用作为参数的时候,在函数内部修改了引用的值,调用函数后实参的值也跟着改变了。
在这里插入图片描述
在形参前面加上const后,如果函数体内部试图修改引用的值,编译器就直接报错了!
在这里插入图片描述


三、函数的高级应用

1.默认参数

可以给函数的形参设置默认值,在传实参的时候,没有传实参就使用默认参数,传了实参就覆盖掉默认参数值。
需要注意的是,如果函数参数中某个位置已经有了默认参数,那么从这个位置往后都必须有默认值。比如一个函数带三个参数,如果第二个参数设置了默认值,那么第三个参数也必须有默认值。
如果函数的参数中只有一个默认参数,那么这个参数就必须放在函数的最后一个位置。
在这里插入图片描述
如果函数声明有默认参数,函数实现就不能有默认参数;或者函数实现有默认参数,函数声明就不能有默认参数。总之两个中至多有一个有默认参数,否则会发生重复定义默认参数错误。 这样定义很容易理解,比如某个参数在函数声明的时候给定的默认值为10,函数实现的时候给了20,这个时候就出现了二义性,编译器不知道按照哪个默认参数来执行了。

//可以
int fun(int a,int b=20,int c=30);
int fun(int a,int b,int c)
{return a+b+c;
}
//可以
int fun(int a,int b,int c);
int fun(int a,int b=20,int c=30)
{return a+b+c;
}
//即使参数的默认值相同,函数声明和函数实现也不可以同时有
int fun(int a,int b=20,int c=30);
int fun(int a,int b=20,int c=30)
{return a+b+c;
}

2.占位参数

函数占位参数:C++中函数的列表里可以有占位参数,用来做占位,调用函数时必须填补该位置。
函数中占位参数只声明变量类型,而不给形参变量。占位参数也可以有默认参数。

void fun(int a,int)  //第二个int就是占位参数
{ ...
}
fun(10,20);   //函数调用void fun(int a,int = 10)  //给占位参数设置默认值
{ ...
}
fun(10);   //函数调用
fun(10,20);  

3.函数重载

函数重载:函数名可以相同,提高复用性。
函数重载需满足的条件:同一个作用于下(全局);函数名相同;函数参数类型不同、或函数参数个数不同、或函数参数的顺序不同。
需要注意的是,函数的返回值不可以作为函数重载的条件
下面的代码就是函数重载的例子。

#include <iostream>
using namespace std;void fun()
{cout<<"fun()"<<endl;
}//以下两个函数参数个数相同,但参数类型不同
void fun(int a)
{cout<<"fun(int a)"<<endl;
}void fun(double a)
{cout<<"fun(double a)"<<endl;
}//以下两个函数参数个数相同,但参数顺序不同
void fun(int a,double b)
{cout<<"fun(int a,double b)"<<endl;
}void fun(double a,int b)
{cout<<"fun(double a,int b)"<<endl;
}int main()
{fun();fun(10);fun(10.0);fun(10,10.0);fun(10.0,10);system("pause");return 0;
}

上面程序运行后的结果如下图所示。
在这里插入图片描述
仅靠函数类型不同是无法完成函数重载的,像下面这样。

void fun()
{cout<<"fun()"<<endl;
}int fun()
{cout<<"fun()"<<endl;
}

但是函数类型结合参数类型、参数个数、参数顺序可以实现函数重载。
在这里插入图片描述
引用作为函数参数重载时,需要注意参数类型前加const和不加const是可以重载成功的。 当函数参数类型前加了const后,函数调用的时候就需要传入常量值。
在这里插入图片描述
函数重载中应尽量避免默认参数的使用,如下面的函数重载例子,如果给默认参数的位置传入实参,则代码不会出错,而只传入一个值的时候,函数调用就会出现二义性,编译器不知道应该调用哪个函数了。

void fun(int a)
{cout<<"fun(int a)"<<endl;
}void fun(int a,int b = 10)
{cout<<"fun(int a,int b = 10)"<<endl;
}fun(10,20);  //合法
fun(10);  //不合法,函数调用出现了二义性

本文参考视频:
黑马程序员匠心之作|C++教程从0到1入门编程,学习编程不再难

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

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

相关文章

Kubernetes-网络

一. 前言 flannel两种容器跨主机通信的方案&#xff0c;其中UDP模式是IP in UDP&#xff0c;即三层报文封装在UDP数据包中通信&#xff1b;而vxlan模式则是MAC in UDP&#xff0c;即二层报文封装在UDP数据包中通信 flannel UDP模式和vxlan模式都对数据包做了封解包&#xff0c…

为什么我不建议大学生接公司单?

大家好&#xff0c;我是鱼皮。前两天&#xff0c;我 编程导航 的鱼友提了个问&#xff1a;大学生怎么接公司的单赚点零花钱&#xff1f; 然后我很认真地评论了一句&#xff1a;我不建议大学生接公司单。 这位小伙伴很认真&#xff0c;又通过微信单独问我&#xff1a; 想了想&am…

Mybatis行为配置之Ⅰ—缓存

专栏精选 引入Mybatis Mybatis的快速入门 Mybatis的增删改查扩展功能说明 mapper映射的参数和结果 Mybatis复杂类型的结果映射 Mybatis基于注解的结果映射 Mybatis枚举类型处理和类型处理器 再谈动态SQL Mybatis配置入门 Mybatis行为配置之Ⅰ—缓存 Mybatis行为配置…

【Midjourney】AI绘画新手教程(一)登录和创建服务器,生成第一幅画作

一、登录Discord 1、访问Discord官网 使用柯學尚网&#xff08;亲测非必须&#xff0c;可加快响应速度&#xff09;访问Discord官方网址&#xff1a;https://discord.com 选择“在您的浏览器中打开Discord” 然后&#xff0c;注册帐号、购买套餐等&#xff0c;在此不做缀述。…

3D目标检测(教程+代码)

随着计算机视觉技术的不断发展&#xff0c;3D目标检测成为了一个备受关注的研究领域。与传统的2D目标检测相比&#xff0c;3D目标检测可以在三维空间中对物体进行定位和识别&#xff0c;具有更高的准确性和适用性。本文将介绍3D目标检测的相关概念、方法和代码实现。 一、3D目…

Python消消乐小游戏(PyGame)

文章目录 写在前面喜羊羊与灰太狼PyGame入门消消乐注意事项写在后面 写在前面 本期内容&#xff1a;基于pygame实现喜羊羊与灰太狼版消消乐小游戏 实验环境 python3.11及以上pycharmpygame 安装pygame的命令&#xff1a; pip install -i https://pypi.tuna.tsinghua.edu.c…

Redis (三)

1、redis复制 简单的概括就是主从复制&#xff0c;master以写为主&#xff0c;Slave以读为主&#xff0c;当master数据发生变化的时候&#xff0c;自动将更新的数据异步同步到其他的slave是数据库。 使用这种机制的话&#xff0c;可以做到读写分离&#xff0c;可以减轻主机负担…

chromium在中文用户名下无法编译的问题

新电脑没有太注意&#xff0c;起用户名的时候用了中文。 在编译chromium104的代码时&#xff0c;因为环境变量有中文导致编译失败&#xff1a; 因为我的电脑默认是使用gbk编码&#xff0c;而不是utf-8编码。 这个问题有三种解决办法&#xff1a; &#xff08;一&#xff09;把…

CMake入门教程【核心篇】添加依赖(add_dependencies)

&#x1f608;「CSDN主页」&#xff1a;传送门 &#x1f608;「Bilibil首页」&#xff1a;传送门 &#x1f608;「本文的内容」&#xff1a;CMake入门教程 &#x1f608;「动动你的小手」&#xff1a;点赞&#x1f44d;收藏⭐️评论&#x1f4dd; 文章目录 1. 基本用法2. 添加目…

DBA技术栈(二):MySQL 存储引擎

2.1 MySQL存储引擎概述 上个业余的图&#xff1a; MyISAM 存储引擎是 MySQL 默认的存储引擎&#xff0c;也是目前 MySQL 使用最为广泛的存储引擎之一。他的前身就是我们在 MySQL 发展历程中所提到的 ISAM&#xff0c;是 ISAM 的升级版本。在 MySQL最开始发行的时候是 ISAM 存…

【LMM 008】Instruction Tuning with GPT-4

论文标题&#xff1a;Instruction Tuning with GPT-4 论文作者&#xff1a;Baolin Peng, Chunyuan Li, Pengcheng He, Michel Galley, Jianfeng Gao 作者单位&#xff1a;Microsoft Research 论文原文&#xff1a;https://arxiv.org/abs/2304.03277 论文出处&#xff1a;– 论文…

在Ubuntu22.04上部署Stable Diffusion

在AI绘画软件领域Stable-Diffusion&#xff08;简称SD&#xff09;在开源领域绝对是不二之选&#xff0c;他的插件方式可以让此软件具有更多的功能&#xff0c;开发者社群为此提供了大量免费高质量的外接预训练模型&#xff08;fine-tune&#xff09;和插件&#xff0c;并持续维…

旋转图像(LeetCode 48)

文章目录 1.问题描述2.难度等级3.热门指数4.解题思路参考文献 1.问题描述 给定一个 n n 的二维矩阵 matrix 表示一个图像。请你将图像顺时针旋转 90 度。 你必须在「原地」旋转图像&#xff0c;这意味着你需要直接修改输入的二维矩阵。请不要使用另一个矩阵来旋转图像。 示…

网络安全—模拟ARP欺骗

文章目录 网络拓扑安装使用编辑数据包客户机攻击机验证 仅做实验用途&#xff0c;禁止做违法犯罪的事情&#xff0c;后果自负。当然现在的计算机多无法被欺骗了&#xff0c;开了防火墙ARP欺骗根本无效。 网络拓扑 均使用Windows Server 2003系统 相关配置可以点击观看这篇文章…

Android开发中“真正”的仓库模式

原文地址&#xff1a;https://proandroiddev.com/the-real-repository-pattern-in-android-efba8662b754原文发表日期&#xff1a;2019.9.5作者&#xff1a;Denis Brandi翻译&#xff1a;tommwq翻译日期&#xff1a;2024.1.3 Figure 1: 仓库模式 多年来我见过很多仓库模式的实…

部署清华ChatGLM-6B(Linux版)

引言 前段时间,清华公布了中英双语对话模型 ChatGLM-6B,具有60亿的参数,初具问答和对话功能。最!最!最重要的是它能够支持私有化部署,大部分实验室的服务器基本上都能跑起来。因为条件特殊,实验室网络不通,那么如何进行离线部署呢? 「部署环境」:CUDA Version 11.0,…

【JavaEE进阶】 关于Spring mvc 响应

文章目录 &#x1f38d;序言&#x1f333; 返回静态⻚⾯&#x1f332;RestController 与 Controller 的关联和区别&#x1f334;返回数据 ResponseBody&#x1f38b;返回HTML代码⽚段&#x1f343;返回JSON&#x1f340;设置状态码&#x1f384;设置Header&#x1f6a9;设置Con…

代码随想录算法训练营第五十七天|647. 回文子串、516.最长回文子序列、动态规划总结篇

代码随想录 (programmercarl.com) 647. 回文子串 1.dp数组及下标含义 我们在判断字符串S是否是回文&#xff0c;那么如果我们知道 s[1]&#xff0c;s[2]&#xff0c;s[3] 这个子串是回文的&#xff0c;那么只需要比较 s[0]和s[4]这两个元素是否相同&#xff0c;如果相同的话&…

斯坦福和 Meta学者发现Gemini在常识推理任务中有较强潜力;初学者GPT:Ai和LLM资源

&#x1f989; AI新闻 &#x1f680; 斯坦福和 Meta学者发现Gemini在常识推理任务中有较强潜力 摘要&#xff1a;斯坦福和Meta的学者发表论文为Gemini正名&#xff0c;他们发现之前对Gemini的评估并不能完全捕捉到其真正的常识推理潜力。他们设计了需要跨模态整合常识知识的任…

鸿蒙开发第一天

一、开发准备工作 1、开发工具的安装 1&#xff09;下载地址&#xff1a;https://developer.huawei.com/consumer/cn/deveco-studio/ 2&#xff09;查询API文档链接&#xff1a;https://developer.huawei.com/consumer/cn/doc/harmonyos-references-V2/syscap-00000014080893…