当前位置: 首页 > news >正文

为什么要有指针和引用类型?

简单说,是为了必要的,且很基础的表达能力 (描述能力)。

0. 数据四要素:名、值、址、型

指针、引用的基础,就是在描述一个数据时,除了这个数据的“值”以外,引入了这个数据的“地址”(以下也会简称“址”),即数据在哪个位置上。

进一步理解,数据数据的“地址”,表达的是这个数据的“实体”,数据的“值”,表达的是数据的“表象”。

就好比说,你老婆的漂亮值是 100,我老婆的也是,但这两个100并不是在描述同一个实体。

相同的值,可能在表达不同的类型的数据,所以,在值、址之外,数据还需要一个“类型”(以下也会简称“型”)。

最后,除了“值”、“址”、“型”为了方便我们在代码中指定某个数据,代码中的多数据,还有一个属性“名字”比如变量或常量的名字(以下也会简称“名”)。有名数据通常就是变量、常量,无名的数据就是“字面量”。

编译型的代码,在编译之后,“名”这个属性通常没有一直存在的必要性(哪怕有带反射),因为程序绝大多数情况下,可以通过地址来精确指代一个数据。
类似的,“型”在代码表达中极其重要,但在在编译之后的程序里,必要性也不高。

1. 猥琐语言的进化史

好,同学们,下面我来举一个语言的例子,让大家肉眼观察这门语言是如何进化出“指针、引用”的。首先我们需要从基础的,数据据的名、值、址的理解开始。

我们即时发明的一种程序语言,名为 “猥琐”计算机语言,有时也简称WS。

1.1 从字面数据开始

让我们WS语言开始写代码:

18
18
由于网上竟然还没有支持猥琐语言的高亮脚本,所以以下只好委屈 C、C++、Go 等语言了,我们的代码标记为它们以获得高亮。

代码中出现两个18!问题马上来了:这两个18表达的是同一个意思吗?如果是同一个意思?那为什么要有两个18?

1.2 上帝说:要有类型……

也就是说,现在,两个数据都有“值”,但是,它们在表达什么?它们没有类型吗?让我们查询一下WS语言手册有什么内置类型……

哇!好棒,内置类型竟然有 年龄、长度、胸围……

我们选长度:

18 : 长度  // WS语言语法:  值 : 类型
18 : 长度  

有“值”有“型”,但还不够——

  • 它们分别是什么东西的长度?
  • 假设代码中有很多地方需要使用到这个长度,难道一直写 18 ,万一哪天要改成 17呢?
  • 如果就是写 18,那为什么要定义两个18?只有一个就够了呀?

好吧,是时候让“名”登场了:

JJ长 = 18 : 长度   // WS是一门国际化语言,支持数据使用汉字作名字
JJ长 = 18 : 长度

1.3 不要重名,不要重名!

等等!!!一前一后两个数据的“名”竟然完全同名!WS语言制定者,你们太不专业了!

  • WS语言制定者:名字相同有什么不合理吗?现实生活中,你老婆叫王大锤,我老婆也叫王大锤啊!
  • WS语言用户:那我们怎么区分哪个是哪个啊!!!!
  • WS语言制定者:当然是看数据的地址,也就实体啊!地址不同,实体就不同;在你家床上睡的王大锤是你老婆,在我家床上睡的是我老婆啊?有什么区分困难吗?
  • WS语言使用者:可是上面代码中,没有体现数据的地址属性啊。

哦!也对。计算机语言中的数据,是如何体现它们(存放在内存中的)地址不同呢? 让我们借鉴一下其它语言吧,包含但不限于:C、C++、C#、Java、Go……

借鉴完毕,原来这么简单呀:就是不直接在代码使用地址表达数据,但是在有需要时,可以通过数据“名字”来映射到数据的“地址”。

"有需要时" 是重点。说明见后。

这么说,数据的名字,还真是不要允许同名的好,万一要同名的话,两个数据就必须处于不同的上下文中……比如复合语句作用域,比如名字空间……

算了算了,猥琐语言主打简洁而猥琐,就让我们简(猥)单(琐)地规定所有变量不允许同名吧!

我的JJ长 = 18 : 长度   
你的JJ长 = 18 : 长度

好,现在我们拥有两个数据:我的JJ长,和你的JJ长。核心问题来了:这两个数据除了名字不一样以外,它们“型”相同、“值”相同,所以,它们是同一个数据吗?

1.4 地址不同,才是真的不同

当然不是!我的JJ在我这里,你的JJ在你这里。

同学: 老师,偶尔也会在王大锤(们)那里。
老师:你们在说什么?

也就是说,“我的JJ长”和“你的JJ长”,值相同,型相同,名不同,址不同。

“址”肯定代表一个数据实体。而“名”,如前所述,主要是给程序员使用的,它有时代表“值”,有时代表“址”。

[重点]

  • 有的计算机语言,在某些上下文可以自行决定这个名字表达的是“值”,还是“址”,即左值右值之分,在无法自动区分的情况下,当需要从名到址转换时,采用一个特殊的操作来表达,比如C、Go、C++中用特定的“取址操作符”(通常是 &) ;
  • 而有的语言,几乎都可以纯粹通过上下文来判断,比如 Java。这类语言通常就是把“型”和“名”的作用做了硬性绑定:某些“型”的数据,它的“名”只表达值,某些“型”的数据,它的“名”可以表达“址”。

1.5 当数据需要传递……

猥琐语言少不了有函数。现在我们就需要一个叫“增大术”的函数,长这样:

func 增大术 ( jjl : 长度 ) -> boolean {if jjl <= 5 :输出 "根基太小了,恕本医师无能为力"return falseif jjl >= 30 :输出 "请不要过份追求肉体上的尺寸!内心的强大才是真正的强大!"return falsejjl++return true
}

可以把“增长术”这个函数,理解为一场“手术”,所以它返回手术是否成功,而不是返回新长度;同时,它动刀的是原有长度,同样不是返回新长度。

由此,我们预期:

你的JJ长 = 18 : 长度
增大术 (你的JJ长)输出 你的JJ长  // 应该得到 19

但是,问题来了, 代码中第二行的, 传入 增大术函数的 你的JJ长 ,现在这个“名”,它表达的是对应数据的“值(表象)”?还是“址”(实体)呢?

显然得是后者!显然没有哪一位大神医师,能通过计算一个18+1得到19,就让你身上的某个东西从18变成19,你必须掏出实体并且放到手术台上啊!

猥琐语言使用者(医生角色):“来,这位患者,请把“你的JJ长”的实体,传送过来,摆在这里,我要动刀(修改)了”

猥琐语言制定者:“等一下,让我想想……”

没错,是时候想一想WS语言的下一步发展了。如前所述,我们有两个选择:

  1. 通过增加明确的表达方式(比如一个符号),来区分一个数据的名字是“值”或是“址”(指针);
  2. 通过将“型”和“名”的作用硬性绑定,让特定的某些类型的数据,名字即可表达数据的“址”(常被称为“引用类型”),而另一些类型的数据,名字就永远只能表达“值”(常被称为“值类型”)

选择1,是C++的路;选择2,是Java的路。

选择在1和2之间来回混的,是 go语言的路。

无论何种选择,反正,指针或引用,就这么引入了。让我们都给个例子:

(一)、 C++风格

func 增大术 ( jjl : *长度 ) -> boolean { // 注意,现在入参的类型是 “ *长度 ”...
}你的JJ长 = 18 : 长度
增大术 ( & 你的JJ长) // 注意多了一个取址符 & 输出 你的JJ长  // 得到 19

(二)、Java风格

先规定 长度 是值类型(不能表达址),再特意搞出一种对应类型,叫 “长度的包装箱”,是引用类型:

func 增大术 ( jjl : 长度的包装箱 ) -> boolean { // 注意,现在入参的类型是 “长度的包装箱”...
}你的JJ长 = 18 : 长度
放在这个箱子里的你的JJ长 = 装箱操作(你的JJ长) // 注意有个装箱操作增大术 ( 放在这个箱子里的你的JJ长 ) // 注意实参现在放在箱子里再传过去……你的JJ长 = 拆箱操作(放在这个箱子里的你的JJ长) // 注意这里拆快递了输出 你的JJ长  // 得到 19

2 最后,回到问题

指针和引用当然还有别的用处,且有既有紧密关系又有重大区别。但都不是问题“为什么要有指针和引用类型”的重点了,因为本文已经讲了“为什么需要指针或引用”的一个必要条件。

相关文章:

为什么要有指针和引用类型?

简单说&#xff0c;是为了必要的&#xff0c;且很基础的表达能力 &#xff08;描述能力&#xff09;。 0. 数据四要素&#xff1a;名、值、址、型 指针、引用的基础&#xff0c;就是在描述一个数据时&#xff0c;除了这个数据的“值”以外&#xff0c;引入了这个数据的“地址…...

vivado INTERNAL_VREF

内部 具有差分输入缓冲器的单端I/O标准需要输入参考 电压&#xff08;VREF&#xff09;。当I/O组中需要VREF时&#xff0c;您可以使用专用VREF 引脚作为外部VREF电源&#xff0c;或使用INTERNAL_VREF内部生成的VREF 属性&#xff0c;或者对于UltraScale设备上的HP I/O组&#x…...

VScode通过Graphviz插件和dot文件绘制层次图,导出svg

1、安装插件 在VScode中安装Graphviz Interactive Preview插件&#xff0c;参考。 2、创建dot文件 在本地创建一个后缀为dot的文件&#xff0c;如test.dot&#xff0c;并写入以下内容&#xff1a; digraph testGraph {label "层次图";node [shape square; widt…...

MMCV 核心组件分析(一):整体概述

概述 MMCV 是计算机视觉研究的基础库&#xff0c;并提供以下功能。...

阵列信号处理学习笔记(一)--阵列信号处理定义

阵列信号 阵列信号处理学习笔记&#xff08;一&#xff09;–阵列信号处理定义 阵列信号处理学习笔记&#xff08;二&#xff09;–空域滤波基本原理 文章目录 阵列信号前言一、阵列信号处理定义1.1 信号1.2 阵列 二、雷达数据中哪些属于空间采样总结 前言 MOOC 阵列信号处理…...

[HTML]一文掌握

背景知识 主流浏览器 浏览器是展示和运行网页的平台&#xff0c; 常见的五大浏览器有 IE浏览器、火狐浏览器&#xff08;Firefox&#xff09;、谷歌浏览器&#xff08;Chrome&#xff09;、Safari浏览器、欧朋浏览器&#xff08;Opera&#xff09; 渲染引擎 浏览器解析代码渲…...

ABAP使用SQL直接更新数据库与使用IN UPDATE TASK的区别

1. 背景 刚接触ABAP的小伙伴常常会有这样的疑问&#xff0c;为什么不直接使用Open SQL直接更新数据库&#xff0c;而要把对DB的操作封装到IN UPDATE TASK中呢&#xff1f; 对于这个问题&#xff0c;比较常见的解释是&#xff0c;IN UPDATE TASK的方式会保证数据更新的一致性。…...

Android GWP-Asan使用与实现原理

目录 一、 背景 二、GWP-Asan介绍 2.1 什么是GWP-ASan 2.2 GWP-Asan与其他几类工具对比 2.3 GWP-ASan与其它内存分配器的兼容性 三、GWP-Asan如何使用 3.1 app进程 3.2 native进程 四、GWP-Asan实现原理 4.1 进程启用GWP-Asan 4.2 初始化 4.3 内存分配 4.3.1 内存…...

SpringBoot 跨域请求处理全攻略:从原理到实践

文章目录 SpringBoot 如何处理跨域请求&#xff1f;你能说出几种方法&#xff1f;跨域请求概述跨域解决方案1. 使用CrossOrigin注解2. 使用WebMvcConfigurer配置类3. 使用过滤器&#xff08;Filter&#xff09;4. 使用Spring Security处理CORS5.使用Spring Cloud Gateway处理CO…...

vulnhub——Ai-Web1靶机渗透

Ai-Web1靶机渗透 靶机下载&#xff1a; 官网地址&#xff1a;https://www.vulnhub.com/entry/ai-web-1,353/ 攻击机&#xff1a;kali2024 一、信息收集 发下目标主机的IP为&#xff1a;192.168.201.141 用nmap工具扫描一下对方主机和服务 发现他打开了80端口 发现搜不到于是…...

sqlalchemy事件监听

sqlalchemy事件监听 SQLAlchemy 中的事件监听允许您在特定事件发生时执行自定义的 Python 代码。这些事件可以是与ORM(对象关系映射)或核心组件相关的操作,比如表、类、会话或事务的插入、更新、删除等操作。通过事件监听,您可以实现日志记录、审计或执行业务规则等功能。…...

【Django+Vue3 线上教育平台项目实战】Celery赋能:优化订单超时处理与自动化定时任务调度

文章目录 前言⭐✨&#x1f4ab;&#x1f525;&#x1f4d6;一、Celery⭐1.基本概念及介绍:✨2.使用步骤&#x1f4ab; 二、订单超时 取消订单&#xff08;Celery&#xff09;&#x1f525;具体实现流程&#x1f4d6; 前言⭐✨&#x1f4ab;&#x1f525;&#x1f4d6; 在构建复…...

CSS3 教程

CSS3 教程 引言 CSS3&#xff0c;即层叠样式表的第三代&#xff0c;是网页设计和开发中不可或缺的技术之一。它为HTML元素提供了丰富的样式定义&#xff0c;使得网页不仅内容丰富&#xff0c;而且外观美观、交互性强。本教程将详细介绍CSS3的基础知识、高级特性以及最佳实践&…...

树与二叉树学习笔记

树与二叉树 计算机中的树树的概念树的类型 什么是二叉树二叉树&#xff1a;定义与特点二叉树&#xff1a;前序、中序、后序遍历二叉树&#xff1a;深度、广度优先遍历二叉树&#xff1a;线索化二叉树&#xff1a;序列化与反序列化 haffman树平均编码长度构建haffman树haffman树…...

消费金融系统开发回忆录

架构设计图 整个支付链路上的功能 支付系统应该有&#xff1a;账户管理、渠道管理、支付管理、对账管理、清算管理、结算管理 一笔支付订单&#xff0c;在支付系统侧就是要记录清楚&#xff0c;谁发起的、对哪个商品进行支付、通过哪个渠道支付、支付时间、支付结果等…...

org.springframework.context.ApplicationContext发送消息

1、创建消息的实体类 package com.demo;/*** 监听的实体类**/ public class EventMessage {private String name;public EventMessage(String name) {this.name name;}public String getName() {return name;}public void setName(String name) {this.name name;} }2、创建消…...

Java8-21新特性

简介 由于Java官方最近更新越来越频繁&#xff0c;而长期支持维护的版本LTS版每隔几年才推出一个&#xff0c;大规模商用的JDK只可能选择LTS版&#xff0c;因此这里只简单记录JDK8&#xff0c;11&#xff0c;17&#xff0c;21。 jdk8 Lambda表达式&#xff1a; Lambda表达式…...

NodeJS系列面试题

大家好&#xff0c;我是有用就扩散&#xff0c;有用就点赞。 有没有写过Koa中间件&#xff0c;说一下中间件原理&#xff0c;介绍下自己写过的中间件 koa本来就是一个轻量级框架&#xff0c;本身支持的功能并不多&#xff0c;功能都是通过中间件来实现不同的需求。开发者可以通…...

QXlsx读写excel

QXlsx读写excel 安装 QXlsx使用 qmake使用 CMake 基本用法1. 写入 Excel 文件2. 读取 Excel 文件 详细用法1. 设置单元格样式2. 合并单元格3. 创建图表4. 设置列宽和行高 完整示例 QXlsx 是一个用于在 Qt 应用中读写 Excel 文件的第三方库。它提供了丰富的 API&#xff0c;可以…...

昇思25天学习打卡营第13天 | mindspore 实现 ShuffleNet 图像分类

1. 背景&#xff1a; 使用 mindspore 学习神经网络&#xff0c;打卡第 13 天&#xff1b;主要内容也依据 mindspore 的学习记录。 2. 迁移学习介绍&#xff1a; mindspore 实现 ShuffleNet 图像分类&#xff1b; ShuffleNet 基本介绍&#xff1a; ShuffleNetV1 是旷视科技提…...

rknn优化教程(二)

文章目录 1. 前述2. 三方库的封装2.1 xrepo中的库2.2 xrepo之外的库2.2.1 opencv2.2.2 rknnrt2.2.3 spdlog 3. rknn_engine库 1. 前述 OK&#xff0c;开始写第二篇的内容了。这篇博客主要能写一下&#xff1a; 如何给一些三方库按照xmake方式进行封装&#xff0c;供调用如何按…...

线程同步:确保多线程程序的安全与高效!

全文目录&#xff1a; 开篇语前序前言第一部分&#xff1a;线程同步的概念与问题1.1 线程同步的概念1.2 线程同步的问题1.3 线程同步的解决方案 第二部分&#xff1a;synchronized关键字的使用2.1 使用 synchronized修饰方法2.2 使用 synchronized修饰代码块 第三部分&#xff…...

React Native在HarmonyOS 5.0阅读类应用开发中的实践

一、技术选型背景 随着HarmonyOS 5.0对Web兼容层的增强&#xff0c;React Native作为跨平台框架可通过重新编译ArkTS组件实现85%以上的代码复用率。阅读类应用具有UI复杂度低、数据流清晰的特点。 二、核心实现方案 1. 环境配置 &#xff08;1&#xff09;使用React Native…...

【单片机期末】单片机系统设计

主要内容&#xff1a;系统状态机&#xff0c;系统时基&#xff0c;系统需求分析&#xff0c;系统构建&#xff0c;系统状态流图 一、题目要求 二、绘制系统状态流图 题目&#xff1a;根据上述描述绘制系统状态流图&#xff0c;注明状态转移条件及方向。 三、利用定时器产生时…...

sqlserver 根据指定字符 解析拼接字符串

DECLARE LotNo NVARCHAR(50)A,B,C DECLARE xml XML ( SELECT <x> REPLACE(LotNo, ,, </x><x>) </x> ) DECLARE ErrorCode NVARCHAR(50) -- 提取 XML 中的值 SELECT value x.value(., VARCHAR(MAX))…...

NFT模式:数字资产确权与链游经济系统构建

NFT模式&#xff1a;数字资产确权与链游经济系统构建 ——从技术架构到可持续生态的范式革命 一、确权技术革新&#xff1a;构建可信数字资产基石 1. 区块链底层架构的进化 跨链互操作协议&#xff1a;基于LayerZero协议实现以太坊、Solana等公链资产互通&#xff0c;通过零知…...

多种风格导航菜单 HTML 实现(附源码)

下面我将为您展示 6 种不同风格的导航菜单实现&#xff0c;每种都包含完整 HTML、CSS 和 JavaScript 代码。 1. 简约水平导航栏 <!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta name"viewport&qu…...

优选算法第十二讲:队列 + 宽搜 优先级队列

优选算法第十二讲&#xff1a;队列 宽搜 && 优先级队列 1.N叉树的层序遍历2.二叉树的锯齿型层序遍历3.二叉树最大宽度4.在每个树行中找最大值5.优先级队列 -- 最后一块石头的重量6.数据流中的第K大元素7.前K个高频单词8.数据流的中位数 1.N叉树的层序遍历 2.二叉树的锯…...

鸿蒙DevEco Studio HarmonyOS 5跑酷小游戏实现指南

1. 项目概述 本跑酷小游戏基于鸿蒙HarmonyOS 5开发&#xff0c;使用DevEco Studio作为开发工具&#xff0c;采用Java语言实现&#xff0c;包含角色控制、障碍物生成和分数计算系统。 2. 项目结构 /src/main/java/com/example/runner/├── MainAbilitySlice.java // 主界…...

AGain DB和倍数增益的关系

我在设置一款索尼CMOS芯片时&#xff0c;Again增益0db变化为6DB&#xff0c;画面的变化只有2倍DN的增益&#xff0c;比如10变为20。 这与dB和线性增益的关系以及传感器处理流程有关。以下是具体原因分析&#xff1a; 1. dB与线性增益的换算关系 6dB对应的理论线性增益应为&…...