从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.mzph.cn/news/596857.shtml

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

相关文章

js统一公共请求处理与常用工具封装

一个完整的前端项目往往会进行一些必要的抽取公用代码进行封装&#xff0c;这里记录js常用工具及统一的公共请求的封装。 一 2017年 第一版web管理后台在用 web后台管理页面用 /*** Created by hua on 2017/8/24.*/ var requestResult{success :0,failure:1,failureMsg:2 }j…

Ubuntu上使用node搭建本地静态http服务器

1.搭建步骤 1.安装Node.js。首先确保你的Ubuntu系统已经安装了Node.js。如果没有安装&#xff0c;可以通过以下命令进行安装&#xff1a; sudo apt-get update sudo apt-get install nodejs #安装nodejs 2.安装npm。npm是Node.js的包管理器&#xff0c;一般会随着Node.js一…

Minio部署在服务器上,分享图片等文件提示,签名不对

问题描述: 上传没问题 下载没问题 就是分享有问题,签名有问题 找了很多解释,什么nginx代理问题啊,什么端口问题啊 什么防火墙问题啊 都是扯淡,一点用没有 最后发现,我的分享链接是127.0.0.1的地址,并不是我的服务器本机的地址 我访问图片都是要把ip改了再去访问,但是一开始并没…

HttpSession的使用

1 HttpSession 概述 在 Java Servlet API 中引入 session 机制来跟踪客户的状态。session 指的是在一段时间内&#xff0c;单个客户与 Web 服务器的一连串相关的交互过程。在一个 session 中&#xff0c;客户可能会多次请求访问同一个网页&#xff0c;也有可能请求访问各种不同…

【JavaSE】P1~P32 进制,字节,Java代码规范,常量,变量,运算符

目录 IDEA常用快键键和快捷用法一、需要复习的重难点概念1 进制、字节、DOS操作命令语句进制及转化字节DOS系统命令提示符 2 Java 常用代码规范3 常量及常量的打印4 变量数据类型及取值范围变量的概念和使用数据类型转换ASCII码表&#xff08;128种&#xff09;基本数据类型极其…

显示所有中国城市需要多少个汉字?

显示所有中国城市需要多少个汉字呢&#xff1f; 需要3678个汉字&#xff0c;看看我怎么知道的。 第一步&#xff1a;先找到中国的所有城市的名称 去哪里找到中国的所有城市的名称呢&#xff1f; 进入中国天气网&#xff1a;http://www.weather.com.cn/ 使用 F12 打开浏览器的调…

Excelize 入选“2023开源创新榜”优秀开源项目

近日&#xff0c;由中国科协科学技术传播中心、中国计算机学会、中国通信学会、中国科学院软件研究所共同主办&#xff0c;CSDN 承办的 2023 开源创新榜专家评审会在国家科技传播中心成功举办。Excelize 电子表格文档开源基础库入选“2023开源创新榜”优秀开源项目。 评审委员…

SwiftUI 打造一款可收缩的 HStack(二):对齐+ZStack

概览 在上篇 SwiftUI 打造一款可收缩的 HStack(一):“原汤化原食” 博文里,我们讨论了如何用 HStack 自身来实现可收缩的“HStack”。 而在本篇中,我们将尝试利用 SwiftUI 对齐 + ZStack 的方式完成相同的功能。 在本篇博文中,您将学到以下内容: 概览1. SwiftUI 中的对…

商业综合体能源管理系统功能有哪些?能够为企业带来哪些价值?

随着IT行业的迅猛发展&#xff0c;仅仅实现智能控制已无法满足当前绿色低碳发展的要求&#xff0c;随着智能设备的增多&#xff0c;同时也产生了越来越多的信息孤岛。通过信息技术构建能源管理系统&#xff0c;可以实现先进、智能、经济、可行的商业综合体能源管理解决方案。 …

静态网页设计——校园官网(HTML+CSS+JavaScript)

前言 声明&#xff1a;该文章只是做技术分享&#xff0c;若侵权请联系我删除。&#xff01;&#xff01; 使用技术&#xff1a;HTMLCSSJS 主要内容&#xff1a;对学校官网的结构进行模仿&#xff0c;对布局进行模仿。 主要内容 1、首页 首页以多个div对页面进行分割和布局…

解析为什么Go语言要使用[]rune而不是string来表示中文字符

众所周知&#xff0c;Go语言中有以下这些数据类型。但rune32这个go语言特有的数据类型&#xff0c;比较有意思却经常遭到忽视。所以今天探索学习一下这个数据类型的功能、用法。 Go基本数据类型 布尔&#xff1a;bool 字符串&#xff1a;string 整数&#xff1a; int int8 …

GitHub项目推荐:IDE-3D

项目地址 GitHub - MrTornado24/IDE-3D: [SIGGRAPH Asia 2022] IDE-3D: Interactive Disentangled Editing For High-Resolution 3D-aware Portrait Synthesisx 项目简述 这是一个交互式的3D画图工具。无论是改图还是成图&#xff0c;都能使用。是一个很有意思的项目。 项目…

安卓和Android是两种不同的操作系统?

实际上&#xff0c;安卓和Android并不是同一种操作系统&#xff01; Android是由Google开发并维护更新的一款操作系统&#xff0c;目前仅能运行在Pixel手机上。 Google Pixel 与 iPhone手机&#xff1a;哪个更好&#xff1f;Google Pixel 与 Apple iPhone哪个手机才是性价比最…

(1)(1.13) SiK无线电高级配置(一)

文章目录 前言 1 监控链接质量 2 诊断范围问题 3 MAVLink协议说明 前言 本文提供 SiK 遥测无线电(SiK Telemetry Radio)的高级配置信息。它面向"高级用户"和希望更好地了解无线电如何运行的用户。 &#xff01;Tip 大多数用户只需要 SiK Radio v2 中提供的基本…

74. 搜索二维矩阵

给你一个满足下述两条属性的 m x n 整数矩阵&#xff1a; 每行中的整数从左到右按非严格递增顺序排列。每行的第一个整数大于前一行的最后一个整数。 给你一个整数 target &#xff0c;如果 target 在矩阵中&#xff0c;返回 true &#xff1b;否则&#xff0c;返回 false 。…

三段式电流保护与自动重合闸MATLAB仿真模型

微❤关注“电气仔推送”获得资料&#xff08;专享优惠&#xff09; 前加速、后加速的区别&#xff1a; 前加速是保护装置不判别是永久性故障还是瞬时故障&#xff0c;直接跳闸&#xff0c;然后经重合闸装置来纠正&#xff1b;后加速是保护装置是先判别故障类型有选择性跳闸 …

对话惠买集团董事长兼CEO杜瑞勇:直播电商粗放时代结束,如何用AI+XR打造精细化的智慧直播生态?

“ 未来将是专业选手精细化运营的智慧直播时代。“ 整理 | 梦婕 编辑 | 渔舟 出品&#xff5c;极新&#xff06;北京电子商务协会 直播电商在经过爆发式增长后&#xff0c;从业者不断涌入&#xff0c;竞争日趋激烈&#xff0c;行业发展必然将会进入到一个缓慢增长阶段。直播…

MySQL自定义时间间隔抽稀

MySQL自定义时间间隔抽稀 表设计数据如下按分钟抽稀按小时抽稀按天抽稀 表设计 create table monitor (tid varchar(255) not null,save_date datetime not null,tlevel decimal(10, 2) null,primary key (tid, save_date) );数据如下 按分钟抽稀 SELECT t2…

D50|单调栈

739.每日温度 初始思路&#xff1a; 暴力解法但是会超时。 class Solution {public int[] dailyTemperatures(int[] temperatures) {int[] answer new int[temperatures.length];for(int i 0;i<temperatures.length;i){for(int j i;j<temperatures.length;j){if(te…

FS4412系统移植及开发板启动过程

FS4412是基于samsung的arm Cortex-A9的Exynos4412的板子&#xff0c;Exynos4412采用了32nm HKMG工艺&#xff0c;是samsung的第一款四核芯片。 Windows装机过程&#xff1a; 1、准备Windows系统镜像、U盘启动盘 2、进入BIOS选择启动方式&#xff08;U盘启动&#xff09; 3、…