IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> 【C/C++】Java程序员理解C++方法签名中结构体指针的引用的作用 -> 正文阅读

[C++知识库]【C/C++】Java程序员理解C++方法签名中结构体指针的引用的作用

1. 前言

  • 以往学习过程中将 指针和引用 作为平行的概念,很容易混淆。本文第一件事需要搞懂他们属于什么维度的东西。

  • 提出 指针和引用有什么区别? 本身就是一个很糟糕的提问方式。应该先将指针这个概念剥离出命题,得到正确的问法:方法签名中,变量声明为普通类型和引用类型有什么区别?。解决了第一个问题后,如果已经对结构体、指针、引用不陌生了,那么研究结构体指针的引用的作用就好理解了。

  • & 作为操作符的用法,不是本文重点,将不做介绍。本文仅梳理&方法签名中的意义。

  • 文末联系Java中方法除了基本类型都为引用传递的设计,加深对引用的理解。

2. 概念解释

2.1 结构体定义

typedef struct Goods {
	int code;
	Goods *next;
} Goods;

2.2 指针和引用属于不同维度

  • 方法内部的形参声明,合法性验证
void f() {
    Goods g1;  // 合法
    Goods* g2; // 合法
    Goods& g3; // 不合法, 编译器报错
}
  • 方法签名的形参声明,合法性验证
// 注意Good& g3 也可以写成 Good &g3,《数据结构》书中大多采用第二种写法
void f(Goods g1, Goods* g2, Goods& g3) { // 均合法
}

综上,Goods& 是引用 能定义在方法签名上而不能在方法内部定义。
基本数据类型、结构体类型、结构体指针类型属于一个范畴A;
引用类型属于另外一个范畴B;
通过方法签名,两个范畴得以联系,A能被声明成B

换言之,指针也有引用类型,并且有实际作用,结构体指针也是指针,方法签名中能声明为引用。

2.3 结构体指针类型的引用

void f(Goods g1, Goods* g2, Goods& g3, Goods*& g4) { // 均合法, Goods*&就是结构体指针类型的引用
}

3. 使用的场景

下题摘自广东工业大学考研真题:

3.1 题目

某仓库用一个带头节点的循环链表L存储各种货物的代码,链表的定义如下:看不懂以下的链表定义点这里

typedef struct Goods {
	int code;
	Goods *next;
} Goods, *GoodsList;

试写一个算法 void f(GoodsList L, GoodsList &Lc, int c),将其中代码code大于c的货物从链表L删除,并将删除的货物组成的一个新的带头节点的循环链表。

3.2 题解

3.2.1 审题

题目要求传入L链表,修改L链表,组成一个新的链表

3.2.1 观察函数签名

/* GoodsList 都为指针变量 L */
void f(GoodsList L, GoodsList &Lc, int c) {
	
}
  • 将函数签名翻译一下:
void f(Goods* L, Goods*& Lc, int c) {
	
}

Goods*& Lc 的作用:作为算法最终要得到的链表的指针,不用显式return。
如果用return,等价于:

Goods* f(Goods* L, int c) {
	Goods* p; // 省略初始化及业务逻辑
	return p;
}
  • 使用引用相比于用返回值,有什么特点
  1. 使用返回值,调用层写法:

    Goods* request;
    Goods* response = f(request, 3);
    
  2. 使用引用,调用层写法:

    Goods* request;
    Goods* response;
    f(request, response, 3); // 此时的方法签名,需要有Goods*&的类型,也就是结构体指针的引用
    

    这题使用引用,需要我们在业务逻辑中注意到方法签名中的引用是算法需要返回的指针,就足够解题了。为了更加深刻的理解引用,下文将讨论一个话题:使用引用的必要性是什么?

4. 方法签名上使用引用的必要性

4.1 引例

牧童用绳子牵着牛去吃草。分类讨论牛在方法签名上的应用场景
牧童 == main方法
牛 == main方法定义的变量
绳子 == main方法定义的变量的指针

typedef struct Cow {
	bool wantEat;
	int times;
} Cow ;
typedef struct Visitor {
	bool saw;
	Cow *ownCow;
} Visitor ;
  1. 结构体类型
    牧童放牛,目的是取悦游客。如果牛吃草了,游客就会看。本质是读牛的数据但是不修改。

    void f(Cow cow, Visitor& vistor) {
    	if (cow.wantEat) {
    		vistor.saw = true;
    	}
    }
    
    main方法:
    Cow cow; 
    Visitor vistor;
    cow.wantEat = randonBool(); // 为新创建的牛随机设置想不想吃草的属性
    f(cow, vistor);
    
  2. 结构体引用
    牧童放牛,取悦游客的同时,还不能让牛吃太多,牛每次吃草都要记录。本质上是读牛的数据但是且进行修改。

    void f(Cow& cow, Visitor& vistor) {
    	if (cow.eated && cow.times < 5) {
    		cow.times++;
    		vistor.saw = 1;
    	}
    }
    
    main方法:
    Cow cow; 
    Visitor vistor;
    cow.wantEat = randonBool(); // 为新创建的牛随机设置想不想吃草的属性
    cow.times = randonInt(); // 为新创建的牛随机设置放牧前吃过几次草的属性
    f(cow, vistor);
    
  3. 结构体指针
    牧童放牛,游客发现后,牧童和游客同时握着绑住牛的绳子。绳子就是牛的指针。

    void f(Cow* cow, Visitor& vistor) {
    	vistor.ownCow = cow;
    }
    
    main方法:
    Cow cow; 
    Visitor vistor;
    f(&cow, vistor); // & 这里做取地址符,也就是取到了cow的指针
    
  4. 结构体指针的引用
    牧童放牛,游客也带了一头牛,他们两个交换牛的绳子。本质上,调用方的变量的指针也被改变了

    void f(Cow&* cow, Visitor& vistor) {
    	Cow* temp = vistor.cow;
    	vistor.ownCow = cow;
    	cow = temp;
    }
    
    main方法:
    Cow cow; 
    Visitor vistor;
    f(&cow, vistor); // & 这里做取地址符,也就是取到了cow的指针
    

4.2 结论

如果要对结构体入参用写操作,那么就需要使用引用类型的入参。如果main方法中定义的变量A,传入方法中后将得到新的变量覆盖A,那么方法签名就需要使用结构体指针的引用。

5. Java Web 中对象为引用传递

基于Spring框架的Web 处理层级结构见图
所有requestresponse 都是引用传递,能层层封装包装requestresponse 都是同一个对象,但是有不会传指针的引用,程序无法交换掉或者篡改requestresponse
在这里插入图片描述

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2021-08-07 11:49:05  更:2021-08-07 11:49:44 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年12日历 -2024/12/26 3:54:32-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码
数据统计