C++语法基础:引用

前言

       "打牢基础,万事不愁" .C++的基础语法的学习

引入

        引用是C++里的概念,和C语言里的"指针常量"是类似的.在C++里用得还挺多的,书中明确说明了类对象做参数时,传入类对象的引用.在<<C++ Prime Plus>> 6th Edition第274页有使用推荐 .用引用来回顾指针常量这一用法.

地址的作用

        先看CPU的大致工作流程,不保证完全准确.参考汇编指令_百度百科

        通过高级语言编写的程序由编译器转化成机器指令,交由CPU执行. 机器指令分为操作码和操作数.CPU拿到指令后要做两件事,一是理解操作码,二是操作数据.CPU对内读写寄存器的数据,对外只与内存进行数据交互,而操作内存数据时需要先找到地址,再读写内存数据.

        回到代码层面,如果有以下代码,将发生什么事?

#include<iostream>
using namespace std;int main(void) {int a = 10;a += 10;cout << "a=" << a << endl;
}

         int a=10; 代表了什么?

         程序员视角:在栈区分配一个32位(4字节)空间,写入"10".地址是程序员不知道的;但可以用&a访问变量地址.CPU视角:如果给&a地址,他找到后可以读取值10

        CPU不认识变量,只认识地址.程序员用变量标识数据,方便理解.所以,变量名是地址的别名

        引用的设计思想:原来还是你,变量地址表示变量. 

引用的优点

        C++是按值传递的(将某个值传入函数,不能改变原值,若需要改变原值需要传入地址).他的传值机制是当把某个变量值传入函数中时,会先生成数据副本,例如:

void show(int a){            //传入数据副本cout<<"a="<<a<<endl;
}
=======================
int value=3;
show(value);                //传入的是value的值的副本

        这样会占用多余的内存空间.

        如果形参使用引用类型,则可以解决这个问题.

        其实指针也是一样的,不会产生数据副本,而且引用数据同指针一样,可以修改传入值.

引用声明格式

        数据类型 & 引用变量 =变量 

        举例:

int b = 2;							    //变量赋值
int& b_pref = b;                        //引用声明

        这个不用可以记忆,因为引用的使用,几乎都是在形参里定义引用,传入变量就可以了.

        但需要注意的是:不能将常量赋给引用,如: int &b=2; 这是错误的.

引用的适用范围

       写几行代码来试试

       1>以内置数据类型引用作参数(可以用但不推荐)

int intPref(int& data) {				//内置类型引用做参数data+=1;return data;
}
=======================================
int b = 2;							//声明整数
int& b_pref = b;					//声明引用
int b_value = intPref(b_pref);		//传入引用;
cout << "传入引用得到的值是" << b_value << endl;
cout << "原值是" << b << endl;		//原值已改变,作用同指针能修改传入值
int c = intPref(b);					//传入变量给引用,可用;
cout << "变量传入引用得到的值是" << c << endl;
//	int e = intPref(&b);			//错误,提示非常量引用的初始值必须为左值
//	int d = intPref(2);				//错误,提示非常量引用的初始值必须为左值

    ----说明:用起来很别扭,常数不能传给引用,可以传入变量.

        所以书上也没推荐用.形参用值就行了    

int intPref(int data) {			//内置类型值做参数,符合使用习惯data+=1;return data;
}

        2>数组(不能使用引用)

int intPref(int& data) {			//内置类型引用做参数data+=1;return data;
}void intPointer(int* const ip) {		//指针做参数cout << "数组的第1个元素是:" << *ip << endl;
}
===========================================================
int intAr[] = { 10,20 };
int* pInt = intAr;
//	intPref(intAr);						//错误,不能给引用参数传入指针
//	intPref(pInt);						//同上
intPointer(intAr);					    //数组名作为指针常量传给指针const
intPointer(pInt);					    //指针变量传给指针const

----说明:传入数组,书上明确形参只能用指针,引用不能通过编译.

        3>对象(正常用法)

using namespace std;class Person {							     //类声明string description;string name;double money;
public:Person(const string& des, const string& na, double mo) :description(des),name(na), money(mo) {}double getMoney() {return money;}string getDescription() {return description;}	string getName() {return name;}
};void show(Person& person);				    //对象引用作参数(函数原型)
void show(Person& person) {				    //对象引用做参数(函数定义)	cout <<person.getName()<<"拥有的零花钱是:"<< person.getMoney() << endl;
}
=======================================================================
Person Mary("beautiful","Mary" ,5000);		//生成名为Mary的对象
show(Mary);							        //将对象名传给Person&类型的形参

----说明:引用作参数最正确的用法,可以说引用的使用场景就是他了

       好了,上面写了一堆分析理解,结论就一句:使用对象作参数的时候用得上引用,其他都不用

引用的使用场景

        使用场景:

        1)对象引用作形参,调用函数时传入对象,上面一小节说明的内容

        2)使用对象引用作返回值,可以用连续调用函数.

        有个经典例子,"<<"运算符重载. 在<<C++ Prime Plus>> 6th Edition第394页

ostream& operator<<(ostream &os,const Time& t){os<<t.hours<<"hours,"<<t.minutes<<"minutes";return os;
}

        当调用cout<<t ;  (cout是已定义的ostream对象,t是Time对象,)打印出小时和分钟数,因为返回值也是ostream&,所以可以继续调用这个函数,打印其他内容

        如:cout<<t<<"接下来的内容"<<.....endl;

        (小感想:数据结构里有"链表",可以把数据一个个像链条一样串在一起.设计函数时有这种"链函数",将形参类型和返回类型设计成一样,设计思想厉害👍)

====================================================================

        对于其他使用引用作返回值的情形,节约内存空间,原理和传入引用而非传值一样,但个人感觉用处不大,可以不用.如果要用,注意返回的引用必须是已存在的引用(形参里的引用,或者全局变量)才可以,否则有内存泄漏风险.

引用引申内容

左值

        以前理解左值: 等号左边的是左值; 可以取地址的是左值.左值是可以修改的(const左值除外)

        引用类型是一种左值类型. 左值一种"非常量"的类型.

        常见数据类型不多,可以做个小结: 

         常量类型(右值):1)字面常量:如3(整数字面常量),'a'(字符字面常量)

                                   2)类似3+a 这种常量和变量的表达式

                                  3)地址常量:如int a=3; 先定义一个变量a,其地址&a为地址常量

                                                       int b[]={10,20},地址b也是地址常量(指针常量)

         其他的类型:变量,指针(包括const指针,指针const),引用,都是左值.

        左值类型可以用作函数形参,右值不可

左值做形参的各种情况

        变量做形参,可以传入同类型变量,同类型字面常量;

        指针做形参,可以传入同类型指针变量,同类型指针常量.

        const指针和指针const做形参,可以传入指针常量,指针变量.

        引用做形参,可以传入同类型变量,同类型引用

 类对象到底是算变量还是常量?

         其他数据类型,常量,变量,指针都是比较明确的.

        类对象里已经给属性赋值了,那么类对象是常量吗?

        答案就在上面蓝色部分. 类对象应该不是常量,是左值.

引用小结

        引用能做的事,指针都可以做.为什么不用指针呢?笔者估计设计者有目的性:在引用class对象时使用引用类型,其他情况下用指针.那么只要记住一条:凡是用对象做形参的时候,都用引用类型

        C++有些繁杂,就像上一节浅复制深复制分析完后发现可以避开.但引用没法避开,该使用引用的地方还是得用

      引用关键词:专属于对象地址的类型

        

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

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

相关文章

Cmake--学习笔记

&#x1f680;write in front&#x1f680; &#x1f50e;大家好&#xff0c;我是黄桃罐头&#xff0c;希望你看完之后&#xff0c;能对你有所帮助&#xff0c;不足请指正&#xff01;共同学习交流 &#x1f381;欢迎各位→点赞&#x1f44d; 收藏⭐️ 留言&#x1f4dd;​…

leetCode.96. 不同的二叉搜索树

leetCode.96. 不同的二叉搜索树 题目思路 代码 // 方法一&#xff1a;直接用卡特兰数就行 // 方法二&#xff1a;递归方法 class Solution { public:int numTrees(int n) {// 这里把 i当成整个结点&#xff0c;j当成左子树最左侧结点,并一次当根节点尝试// f[ i ] f[ j - 1…

PostgreSQL的系统视图pg_statio_all_indexes

PostgreSQL的系统视图pg_statio_all_indexes 在 PostgreSQL 数据库中&#xff0c;pg_statio_all_indexes 视图提供了有关所有索引的 I/O 活动的统计信息。这些统计信息对于了解索引的使用情况和性能调优非常有帮助。 pg_statio_all_indexes 视图的结构 以下是 pg_statio_all…

基于Java的会员制医疗预约服务管理信息系统

你好呀&#xff0c;我是计算机学姐码农小野&#xff01;如果有相关需求&#xff0c;可以私信联系我。 开发语言&#xff1a;Java 数据库&#xff1a;MySQL 技术&#xff1a;Java技术ssm框架&#xff0c;结合JSPM工作流引擎 工具&#xff1a;IDEA/Eclipse、Navicat、Maven …

10大内网安全管理系统!企业内网安全必备系统

内网安全管理系统对于维护企业网络安全至关重要&#xff0c;它们帮助监控、管理内部网络资源&#xff0c;防止数据泄露和安全威胁。以下是十款知名的内网安全管理系统。 1. 安企神终端安全管理系统 详细介绍&#xff1a; 安企神是针对企业内网安全需求设计的一款综合管理系统&…

记一次windows 资源管理器 explorer.exe无限重启(桌面2秒一直刷新)问题的排查

一. 现象 进入锁屏界面一切正常&#xff0c;输入密码进入桌面后&#xff0c;开始无限刷新&#xff0c;无法正常操作&#xff0c;任务栏也不显示。CtrlAltDel 打开任务管理器&#xff0c;可见windows资源管理器进程时而出现&#xff0c;时而消失。进入安全模式一切正常。window…

kubernetes中使用Helm搭建Redis集群

1. 环境要求 首先需要有kubernetes集群环境&#xff0c;搭建kubernetes集群可以使用kubeSphere、kubespray等工具安装集群。其次要安装helm&#xff0c;并且添加了可用的Chart仓库 2. 确认合适的Chart包 helm官网上搜索redis 找到Star数多的Chart包&#xff0c;一类是redis包…

乐鑫 Matter 技术体验日|快速落地 Matter 产品,引领智能家居生态新发展

随着 Matter 协议的推广和普及&#xff0c;智能家居行业正迎来新的发展机遇&#xff0c;众多厂商纷纷投身于 Matter 产品的研发与验证。然而&#xff0c;开发者普遍面临技术门槛高、认证流程繁琐、生产管理复杂等诸多挑战。 乐鑫信息科技 (688018.SH) 凭借深厚的研发实力与行…

Gin框架基础

1、一个简单的Gin示例 下载并安装Gin: go get -u github.com/gin-gonic/gin1.1 一个简单的例子 package mainimport ("net/http""github.com/gin-gonic/gin" )func main() {// 创建一个默认的路由引擎r : gin.Default()// 当客户端以GET方式访问 /hello…

常见Web认证方式对比

认证是一个在用户或者设备在访问一个受限的系统时&#xff0c;鉴定用户凭据的过程&#xff0c;即确认“你是谁”的问题。最常见的认证用户的方式是通过用户名和密码的形式进行校验&#xff0c;目前存在多种校验方式&#xff0c;本文将对其进行一个简单的对比&#xff0c;使得大…

flutter项目中不能使用在ios样式组件下的组件有哪些

InkWell 未完待续&#xff0c;也请大家补充&#xff0c;评论区见

TensorFlow 的原理与使用

文章目录 TensorFlow 的基本原理1. 计算图&#xff08;Computation Graph&#xff09;2. 张量&#xff08;Tensor&#xff09;3. 会话&#xff08;Session&#xff09;4. 自动微分&#xff08;Automatic Differentiation&#xff09; TensorFlow 的使用安装 TensorFlow基本使用…

DDR3自刷新问题

DDR3 内存中的自刷新和手动刷新是两种不同的刷新机制&#xff0c;它们在目的、操作方式和使用场景上有所不同。让我们来比较这两种刷新方式&#xff1a; 自刷新&#xff09;&#xff1a; 目的&#xff1a;在系统低功耗模式下保持数据完整性。操作&#xff1a;由 DRAM 内部的电路…

160相交链表

解法1&#xff1a; public class Solution {public ListNode getIntersectionNode(ListNode headA, ListNode headB) {// 定义两个指针。// 获得两个链表的长度&#xff0c;将较长的链表先用指针移动到和短链表一样的长度。// 再一个个比较ListNode l1 headA, l2 headB;int …

Scala访问修饰符全解析:掌握类与成员的可见性

&#x1f512; Scala访问修饰符全解析&#xff1a;掌握类与成员的可见性 在面向对象编程中&#xff0c;控制类成员的可见性是封装性的核心。Scala作为一门强类型的面向对象编程语言&#xff0c;提供了一套丰富的访问修饰符来实现这一点。本文将深入探讨Scala中的访问修饰符&am…

在我们的大数据平台(XSailbaot)上进行企业级数据建模的思路

1. 背景 笔者所在的公司是差不多二十年前搞CIM&#xff08;公共信息模型的&#xff09;起家的。当时公司的前辈搞了基于CIS协议的模型服务器、数据服务器、模式编辑器等&#xff0c;形成了一套基于公共信息模型建模的平台系统。其中可视化建模&#xff0c;建好了模式类以后&am…

Kotlin中对空的很多处理

代码图片直观效果 逐行解释Kotlin中对空的各种情况的使用 private fun testNull() {val flag 1var name: String? nullvar user: User? // 有警告, 因为下面的赋值可以和这一行定义合并var zhangUser: User? User()var wangUser: User User() // 提示Explicitly given t…

AttGAN实验复现 2024

AttnGAN 代码复现 2024 文章目录 AttnGAN 代码复现 2024简介环境python 依赖数据集TrainingPre-train DAMSMTrain AttnGAN SamplingB_VALIDATION 为 False (默认)B_VALIDATION 为 True 参考博客 简介 论文地址&#xff1a; https://arxiv.org/pdf/1711.10485.pdf 代码 python…

C++: 如何用C语言实现C++的虚函数机制?

前言 在 googletest的源码中&#xff0c;看到gtest-matchers.h 中实现的MatcherBase 类自定义了一个 VTable&#xff0c;这种设计实现了一种类似于C虚函数的机制。C中的虚函数机制实质上就是通过这种方式实现的&#xff0c;本文用c语言自定义虚函数表VTable实现了一下virtual的…

Workerman在线客服系统源码,附搭建教程

源码介绍&#xff1a; Workerman在线客服系统源码。 workerman是一个高性能的PHP socket 服务器框架&#xff0c;workerman基于PHP多进程以及libevent事件轮询库&#xff0c;PHP开发者只要实现一两个接口&#xff0c;便可以开发出自己的网络应用&#xff0c;例如Rpc服务、聊天…