从C到C++入门篇(三)引用;引用的本质

news2024/9/22 1:38:24

Reference & 引用

变量名,本身是一段内存的引用,即别名(alias)。此处引入的引用,是为己有变
量起一个别名。

int a= 500; //变量名.实质是一段内存空间的别名

(int)0x0002345=500;

引用的规则

  1. 引用,是一种关系型声明,而非定义。
    不能独立存在,必须初始化,且与原类型保持一致,且不分配内存。
  2. 声明关系,一经声明,不可变更。
  3. 可对引用,再次引用。多次引用的结果,
    是某一变量具有多个别名,多个别名间是平行关系。
  4. 辨别引用与其它,&符号前有数据类型时,
    是引用,其它皆为取地址或按位与。
#include <iostream>
using namespace std;
int main()
{
    int a,b;
    int &ra = a; //声明引用变量 ra,并初始化为 a 变量的引用
//    int &ra = b; //错误,不可更改原有的引用关系
//    float &rb = b; //错误,引用类型不匹配
    cout<< sizeof(a)<<"  "<< sizeof(ra)<<endl; // 4  4
    cout<<&a<<"  "<<&ra<<endl;  //变量与引用具有相同的地址。//0x62fe0c  0x62fe0c
    a=100;
    cout<<a<<"  "<<ra<<endl;//100  100
    ra=200;
    cout<<a<<"  "<<ra<<endl;//200  200

    int &rra = ra; //可对引用再次引用,但是不能建立引用的引用 (int & &rra = ra; 是错误的)
    // 表示 a 变量有两个别名,分别是 rra 和 ra
    cout<<a<<"  "<<ra<<"  "<<rra<<endl;//200  200  200
    cout<<&a<<"  "<<&ra<<"  "<<&rra<<endl;  //变量与引用具有相同的地址。//0x62fe0c  0x62fe0c  0x62fe0c


    int *p = &ra; //可以对引用取地址,但是不能建立引用的指针 (int & *p=&ra; 是错误的) 引用的本质是对指针的包装,再对其解包没有意义
    cout<<p<<"  "<<&ra<<"  "<<&rra<<endl; //0x62fe04  0x62fe04  0x62fe04

    return 0;
}

引用的应用

交换数据:

#include <iostream>
using namespace std;

void swap(int &a, int &b){
    a^=b;
    b^=a;
    a^=b;
}

int main()
{
    int a=5, b=10;
    cout<<"交换前: a="<<a<<" b="<<b<<endl;
    swap(a, b);
    cout<<"交换后: a="<<a<<" b="<<b<<endl;
    return 0;
}

交换前: a=5 b=10
交换后: a=10 b=5

交换指针:

#include <iostream>
using namespace std;

//交换指针 引用的本质是对指针的再次包装 ; 指针是有引用的 ; 不应该有引用的指针
void swap(char* &p, char* &q){
    char* temp=p;
    p=q;
    q=temp;
}
int main()
{
    char* pchar="hello";
    char* qchar="world";
    cout<<"交换前: pchar="<<pchar<<" qchar="<<qchar<<endl;
    swap(pchar, qchar);
    cout<<"交换后: pchar="<<pchar<<" qchar="<<qchar<<endl;

    return 0;
}

交换前: pchar=hello qchar=world
交换后: pchar=world qchar=hello

深入使用引用

引用的本质是指针,C++对裸露的内存地址(指针)作了一次包装。又取得的指针的优良特
性。所以再对引用取地址,建立引用的指针没有意义。

  1. 可以定义指针的引用,但不能定义引用的引用。
    int a;
    int* p = &a;
    int*& rp = p; // ok
    int& r = a;
    int&& rr = r; // error
    
    引入引用的目的,将问题控制在变量的层次上,而不是提升层次. (消灭指针)
  1. 可以定义指针的指针(二级指针),但不能定义引用的指针。
    int a;
    int* p = &a;
    int** pp = &p; // ok
    int& r = a;
    int&* pr = &r; // error  r本质是对指针深层次的包装!
    
    int * & ==> 指针的引用
    int & * ==> 引用的指针
  1. 可以定义指针数组,但不能定义引用数组,可以定义数组引用。
    int a, b, c;
    int* parr[] = {&a, &b, &c}; // ok
    int& rarr[] = {a, b, c}; // error 不能定义引用数组
    //rarr 代表首元素地址;数组中元素是 int& ,rarr代表int & * ,int & *是引用的指针,不被允许的
    
    
    int arr[] = {1, 2, 3};
    //arr代表首元素地址;数组名等价于int[3] ;对他引用 int[3] & ; 本质int * & ==> 指针的引用
    
    int (&rarr)[3] = arr; // ok 可以定义数组引用
    本质是:int[3] &rarr = arr;

常引用

const 引用有较多使用。它可以防止对象的值被随意修改。因而具有一些特性。

     const int a=10;
    //&a;  //取地址a 取出==> const int *
    //int * p=&a; //c++中是不允许的
    const int * p=&a; //正确的写法

    //int &ra=a; //依然不允许
    const int &ra=a; //正确的写法
  1. const 对象的引用必须是 const 的,将普通引用绑定到 const 对象是不合法的。 这
    个原因比较简单。既然对象是 const 的,表示不能被修改,引用当然也不能修改,必须使
    用 const 引用。实际上,const int a=1; int &b=a;这种写法是不合法的,编译不过。
  2. const 引用可使用相关类型的对象(常量,非同类型的变量或表达式)初始化。这个是
    const 引用与普通引用最大的区别。const int &a=2;是合法的。double x=3.14; const int
    &b=a;也是合法的
    const int x=10;
    const int &rx=x; //正确

    int y=10;
    const int &rx=y; //正确
    
    
    int a=10;
    double &ra=a; //error 引用的类型,必须于被引用的类型一致
    const double &ra=a; //使用const 就可以
    
    int &rr=a+6; //error
    const int &rr=a+6; //使用const 就可以

    const int & rv=200;//正确 常量可以赋值
    
    
    
void func(const int & rv ){}
    func(200); //正确 
    func(a+200);//正确 表达式可以赋值

引入一段代码解读const

#include <iostream>
using namespace std;
int main()
{
    int a=200;
    int & ra = a;
    //double & rd = a;  //不加const编译不过的
    const double & rd = a;

    a = 300;
    cout<<"a = "<<a<<endl;//输出:a = 300
    cout<<"ra = "<<ra<<endl;//输出:ra = 300
    cout<<"rd = "<<rd<<endl;//输出了:rd = 200

    cout<<"打印地址"<<endl;
    cout<<"&a = "<<&a<<endl;// &a = 0x62fe04
    cout<<"&ra = "<<&ra<<endl;// &ra = 0x62fe04
    cout<<"&rd = "<<&rd<<endl;// &rd = 0x62fe08


    return 0;
}

实际上,const 引用使用相
关类型对象初始化时发生了如下过程:

const double & rd = a;
其中
double temp=a;
const double & rd = temp;

此时产生了与表达式等值的无名的临时变量,
此时的引用是对无名的临时变量的引用。故不能更改。
const使用了中间变量存储,中间变量是绝对不能更改的;

尽可能使用 const

1,使用 const 可以避免无意修改数据的编程错误。

2,使用 const 可以处理 const 和非 const 实参。否则将只能接受非 const 数据。

3,使用 const 引用,可使函数能够正确的生成并使用临时变量(如果实参与引用参数不匹配,就会生成临时变量)

引用的本质浅析

引用的特性显示引用是: int * const p; 是一个const修饰的指针

#include <iostream>
using namespace std;
struct TypeP
{
    char *p;
};
struct TypeC
{
    char c;
};
struct TypeR
{
    char& r; //把引用单列出来,不与具体的对像发生关系
};


int main()
{

    printf("%d %d %d\n",sizeof(TypeP),sizeof(TypeC),sizeof(TypeR));
    //输出结果为:8 1 8
    //引用的特性显示引用是: int * const p; 是一个const修饰的指针

    return 0;
}

反汇编对比指针和引用

原程序:

#include <iostream>
using namespace std;
void Swap(int *p, int *q)
{
    int t = *p;
    *p = *q;
    *q = t;
}
void Swap(int &p, int &q)
{
    int t = p;
    p = q;
    q = t;
}
int main()
{
    int a = 3; int b =5;
    Swap(a,b);
    Swap(&a,&b);
    return 0;
}

汇编程序:
在这里插入图片描述

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

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

相关文章

【电路笔记】-D类放大器

D类放大器 文章目录 D类放大器1、概述2、D类放大器介绍3、调制4、放大5、滤波6、效率7、总结1、概述 在之前的文章中,放大器的导通角与其效率之间建立了重要的联系。 事实上,基于高导通角的放大器提供非常好的线性度,例如 A 类放大器,但效率非常有限,通常约为 20% 至 30%…

MATLAB基础:数据和变量

今天我们开始学习MATLAB基础知识 1、常用非运算符及其作用 1、“,” 作为程序运行的分隔符&#xff0c;起到分隔语句的作用 2、“;” 同样作为分隔符&#xff0c;与“,”不同的是“;”会在程序运行时隐藏该行语句 如下图&#xff1a; 3、“...” 三个英文句点表示续行符…

深入解析食堂采购系统源码开发:从零开始构建供应链采购管理APP

今天&#xff0c;笔者将与大家共同探讨食堂采购系统源码开发&#xff0c;从零开始构建一个高效的供应链采购管理APP。 一、需求分析 在开始开发之前&#xff0c;首先需要进行详细的需求分析。这一步至关重要&#xff0c;因为它直接影响到系统的功能和架构设计。对于食堂采购系…

达梦数据库系列—30. DTS迁移Mysql到DM

目录 1.MySQL 源端信息 2.DM 目的端信息 3.迁移评估 4.数据库迁移 4.1源端 MySQL 准备 4.2目的端达梦准备 初始化参数设置 兼容性参数设置 创建迁移用户和表空间 4.3迁移步骤 创建迁移 配置迁移对象及策略 开始迁移 对象补迁 5.数据校验 统计 MySQL 端对象及数…

BUG与测试用例设计

一.软件测试的生命周期 需求分析→测试计划→测试设计,测试开发→测试执行→测试评估→上线→运行维护 二.BUG 1.bug的概念 (1)当且仅当规格说明(需求文档)是存在的并且正确,程序与规格说明之间的不匹配才是错误. (2)当需求规格说明书没有提到的功能,判断标准以最终用户为准…

vscode调试nextjs前端后端程序、nextjs api接口

最近有一个项目使用了nextjs框架&#xff0c;并且使用nextjs同时实现了前后端&#xff0c;由于之前前后端都是分离的&#xff0c;前端的调试可以通过在代码种添加debugger或者直接在浏览器中打断点实现&#xff0c;现在想调试后端接口&#xff0c;前面的方式就不适用了。故研究…

【RaspberryPi】树莓派Matlab/Simulink支持包安装与使用

官网支持与兼容性 Raspberry Pi Support from MATLAB - Hardware Support - MATLAB & Simulink Raspberry Pi Support from Simulink - Hardware Support - MATLAB & Simulink Matlab与树莓派兼容性 Simulink与树莓派兼容性 树莓派Matlab&Simulink RaspberryPi支…

项目实战1(30小时精通C++和外挂实战)

项目实战1&#xff08;30小时精通C和外挂实战&#xff09; 01-MFC1-图标02-MFC2-按钮、调试、打开网页05-MFC5-checkbox及按钮绑定对象06--文件格式、OD序列号08-暴力破解09-CE10-秒杀僵尸 01-MFC1-图标 这个外挂只针对植物大战僵尸游戏 开发这个外挂&#xff0c;首先要将界面…

RK3399 Linux 系统,接i2c外设,时好时坏(三)其中一个解决问题方法

在 RK3399 平台上,连接 I2C 设备时,有时可能会遇到时好时坏的问题。这种情况往往与引脚的配置有关。在本文中,我们将讨论如何通过调整引脚的上下拉配置来解决这个问题。 目前瑞芯微芯片,需要调节i2c驱动电流能力的,有以下芯片: 具体来说,我们将把 I2C1 的引脚配置中的…

SpringSecurity专题

目录 一&#xff1a;认证授权 什么是认证授权&#xff1a; 二&#xff1a;权限数据模型 RBAC权限数据模型 2.1基于角色访问权限控制 2.2基于资源访问权限控制 常见的认证方式 1.Cookie-Session 2.jwt令牌无状态认证 三&#xff1a;JWT 1.JWT的组成 2.JWT的使用 四&…

【STC32G12K128开发板】第3-7讲:声音探测传感器

第3-7讲&#xff1a;声音探测传感器 学习目的了解声音探测传感器模块的作用。掌握单片机编程读取声音探测传感器模块引脚输出状态&#xff0c;从而判断周围环境声音强度有没有达到设置的阈值。 声音探测传感器简介 声音探测传感器模块对环境声音强度敏感&#xff0c;常用来检测…

解决Linux桌面初始化问题

问题 启动vnc桌面&#xff0c;提示问题 定位 从[t]csh手册 可以看到&#xff0c;其初始化流程 经定位&#xff0c;是.cshrc的这段代码存在&#xff0c;导致桌面初始化异常。 [wanlin.wangicinfra-cn-172-16-0-115 ~]$ cat .cshrc ...部分省略... # Environment for anac…

模拟电子技术-实验五 单管放大电路仿真实验

实验五 单管放大电路仿真实验 一&#xff0e;实验类型 二&#xff0e;实验目的 1、熟悉multisim的仿真实验法&#xff0c;熟悉multisim中双踪示波器和信号发生器的设置和使用方法。学习电压表的使用方法。 2、熟悉放大电路的基本测量方法&#xff0c;了解使放大电路不失真地…

Spring中@PostConstruct注解的使用

1.描述 1.1 背景 最近在做一个系统交互日志模块&#xff0c;要监控一个http请求&#xff0c;并记录请求与响应日志。项目中使用RestTemplate来发送http请求&#xff0c;所以打算给RestTemplate设置拦截器&#xff0c;来进行自定义操作。但是&#xff0c;只对当前类生效&#x…

《昇思25天学习打卡营第23天|RNN实现情感分类》

使用RNN进行情感分类&#xff1a;基于IMDB数据集的LSTM应用 引言 情感分析是自然语言处理&#xff08;NLP&#xff09;中的一个重要应用&#xff0c;广泛用于电影评论、社交媒体等文本数据的情感分类任务。本文将介绍如何使用递归神经网络&#xff08;RNN&#xff09;实现情感…

InternLM学习笔记

入门岛 1. Linux基础知识 2. Python 基础知识 from collections import Countertext """ Got this panda plush toy for my daughters birthday, who loves it and takes it everywhere. Its soft and super cute, and its face has a friendly look. Its a …

[linux] seqeval安装报错

新建一个新的环境 然后安装&#xff1a; # 不能拷贝别人的环境再安mebert_wash的环境。有冲突。我需要重新安一个空的conda环境&#xff0c;再安装。 # conda create -n wash python3.10 ipykernel python -m pip install --upgrade setuptools python -m pip install --upgr…

函数-递归调用

目录 一、基本介绍 二、递归能解决什么问题&#xff1f; 三、递归案例 1、打印问题 2、阶乘问题 四、递归重要规则 五、课堂练习 1、斐波那契数 2、猴子吃桃问题 3、汉诺塔 一、基本介绍 1、简单地说&#xff1a;递归就是函数自己调用自己&#xff0c;每次调用时传入…

利用python自动化运维i脚本实现远程连接服务器并实现相应命令

目录 前言&#xff1a; 一.调用的python库介绍 二.在主机上安装好相应的库 2.1激活虚拟环境 三.代码实现以及解析 四.效果的实现 五.致谢 前言&#xff1a; 在当今快速发展的技术环境中&#xff0c;自动化运维已成为 IT 基础设施管理的关键组成部分。它不仅可以显著提…

SPSS个人版是什么软件

SPSS是一款数据统计、分析软件&#xff0c;它由IBM公司出品&#xff0c;这款软件平台提供了文本分析、大量的机器学习算法、数据分析模型、高级统计分析功能等&#xff0c;软件易学且功能非常强大&#xff0c;可以使用SPSS制作图表&#xff0c;例如柱状、饼状、折线等图表&…