指针与引用

指针与引用

本文讲解编程语言中指针(Pointer)与引用(Reference)的概念, 并且对比了常见语言中这两个概念的区别.

C++

指针和引用在C++中是非常重要的概念, 初学者很容易在指针和引用的概念上混淆(因为这两者太像了).

如何理解两者的本质:

  • 指针的本质: 存储地址的变量(实体)
  • 引用的本质: 变量的别名

但在汇编层面指针和引用是一样的,只是编译器对两者做了区分,引用可以看作是更加安全的指针,进行了许多限制,大部分情况应该优先使用引用

下面列个表格,对比这两者的区别

  • &的二义性: 既是引用的定义, 也是取地址符
指针 ( *a=&v;) 引用 ( &a=v;)
可以多级 (type **a) ×
可以不用初始化 ×
可以指向 NULL ×
可以改变 ×
有自己独立的地址 ×
sizeof(a) len( *) len()
自增运算 地址++ 变量值++
成员访问 -> .
const(右) * const (指针不可变) & const (未定义)
const(左) const * (指向对象不可变) const & (引用对象不可变)
  • 指针的引用 ( *&r = p;)
  • 引用的指针 ( *p = &r;)

使用场景

优先使用引用,必要时用指针

  • 指针的操作权限更多, 容易带来危险操作

指针的使用场景

  • 实现链表或者树之类的数据结构
  • 传递函数参数 (避免copy引起的开销)

引用的使用场景

  • 传递函数参数 (避免copy引起的开销, 且不需要检查引用是否为NULL)

此外还有函数指针,这里不谈了 (C++的内容实在是繁杂)

Go

Golang中也有指针类型, 但没有引用.

而且Go的指针也与C++中的指针有很多不同之处:

  • 指针值不支持数学运算 (避免指针对内存的任意操作)
  • 不同类型的指针无法直接赋值
  • 局部变量的指针可以被"安全"的返回

这里需要介绍一些关于Go中的函数参数传递的知识.

  • Go中只有值传递 (指针类型一样)

  • 如果需要在函数中修改参数值, 可以使用指针

  • 引用类型变量存储的是地址, 因此可以在参数中修改原值

    Go的变量包括值类型和引用类型, 引用类型只有slice, channel 和 map 三种, 引用类型的特点是变量存储的是地址, 因此传引用类型到函数中修改会影响原值.

Python

Python没有引用, 也没有显式的指针, 只有对象引用, 这和其内存管理方式密切相关.

Python是通过"引用计数"自动管理内存的, 程序中的每个对象的引用个数都会被记录, 当引用个数为0时会被垃圾回收机制回收, 既不需要分配, 也不用担心回收.

Python中一切皆对象, 对象是一个三元组 (Id, Type, Value), 变量和对象之间的关系为引用, 变量更像是指针.

Python的对象类型分为可变(mutable)和不可变(immutable). 可变类型包括 list, dict, set, bytearray, user-defined classes, 这些类型在函数内部修改会影响原值.

这里又会引出浅拷贝和深拷贝的区别. 浅拷贝只复制了对象的引用, 本质共享同一个对象; 深拷贝则是创建了对象的副本, 修改不会影响原值.

Java

Java的数据类型分为基本类型(byte, short, int, long, double, float, char, boolean)和引用类型.

Java中没有指针, 但引用本质上就是"指针", Java引用存储实际就是对象的地址, 引用存储在栈区, 而对象存储在堆区. 区别在于Java引用对指针进行了封装, 使其无法直接操作内存.

Java引用和C++引用存在区别, Java引用有自己的内存 (和C++指针比较像), 存储地址, 而C++引用只是别名.

参考

C++中指针与引用的区别 - 知乎 (zhihu.com)

C++中,引用和指针的区别是什么? - 知乎 (zhihu.com)

C++中“引用”的底层实现 - hoodlum1980 - 博客园 (cnblogs.com)

Go 语言没有引用类型,指针也与众不同 - 知乎 (zhihu.com)

go 值类型与引用类型_欧阳惜竹的博客-CSDN博客

Python学习系列之值类型与引用类型_answer3lin的博客-CSDN博客

Java真的没有“指针”吗? - 知乎 (zhihu.com)

本文转载于网络 如有侵权请联系删除

相关文章

  • picgo+typora+gitee制作图传详细笔记(踩坑心得)

    结合了几个教程,避免踩坑,实践总结如下:1-gitee建立i名字为iimages的仓库 2-到:https://github.com/Molunerfinn/PicGo/releases/tag/v2.3.0-beta.6下载exe安装 3-到http://nodejs.cn/download/下载64位exe,傻瓜式安装,可到cmd使用命令:npm-v和nodejs-v查看版本 配置镜像源:npmconfigsetregistry"https://registry.npm.taobao.org" 然后npminstallpicgo-plugin-gitee-uploader安装插件,重启picgo,到插件搜gitee,发现gitee-uploader已安装 4-到picgo图传设置中gitee配置: repo:gitee仓库地址,格式为:用户名/仓库名,比如我仓库链接为https://gitee.com/dgzde567/images,则填写:/dgzde567/images branch:git分支名称,选填项,所以可填可不填,默认:master token:g

  • 为什么坚持每天原创,网站还是会被算法惩罚?

    有的seo听说,网站要更新原创文章才有排名,所以每天苦哈哈的创作原创文章,而搜索引擎也是如约的给了其比较不错的排名,这时更新原创文章就会有排名,成了网站搜索排名的至理名言,然而好景不长,在某个阳光明媚的早上seoer流下了委屈的泪水,说好的更新原创网站排名就会提高,怎么网站还被百度k站了呢?具体原因出在哪呢?我们通过下面几点进行分析:一.优化手段出现了问题很多人都是自我感觉良好的,都认为自己的优化方案都是可以符合百度要求,但是结果和想象是有很大差距的,往往在过程中会出现一些比较小的问题,这些问题随着时间的延长就会变的越来越大,从而就会出现触犯处罚的标准,这个时候网站就会出现降权了。为此我们应在做seo策略时,多关注百度资源平台相关调整的通知,知名seo论坛中草根SEO的反馈,及时做调整,不过seo标准是一个浮动的存在,我们应一切秉承为用户体验、为用户解决问题的出发点来做seo,相对来说被k的可能性小一些。二.百度数据出现异常大家在出现百度数据库异常的情况后,不要烦躁,一定还要坚持保持之前的方案,这样数据库在稳定后就会自动恢复的,如果没有得到恢复,大家也可以在平台上面进行投诉,一旦投诉成

  • PHP Laravel 上传图片、文件等类封装

    今天把项目中上传功能封装成类,方便后面使用,简单的封装了一下,感觉还不怎么好,后面继续优化。具体代码如下:<?php/**namespaceAppThinkClass;useSymfonyComponentHttpFoundationFileUploadedFile;classUploadClass{/**protected$file;/**private$error='';//上传错误信息private$fullPath='';//绝对地址private$config=array('maxSize'=>31024,//上传的文件大小限制(0-不做限制)'exts'=>array('jpg','jpeg','gif','png','doc','docx','xls','xlsx','ppt','pptx

  • 二、三、四层交换技术的原理是啥?建议收藏!

    交换机交换机的工作原理交换机根据收到数据帧中的源MAC地址建立该地址同交换机端口的映射,并将其写入MAC地址表中。交换机将数据帧中的目的MAC地址同已建立的MAC地址表进行比较,以决定由哪个端口进行转发。如数据帧中的目的MAC地址不在MAC地址表中,则向所有端口转发。这一过程称为泛洪(flood)。广播帧和组播帧向所有的端口转发。交换机的三个主要功能学习:以太网交换机了解每一端口相连设备的MAC地址,并将地址同相应的端口映射起来存放在交换机缓存中的MAC地址表中。转发/过滤:当一个数据帧的目的地址在MAC地址表中有映射时,它被转发到连接目的节点的端口而不是所有端口(如该数据帧为广播/组播帧则转发至所有端口)。消除回路:当交换机包括一个冗余回路时,以太网交换机通过生成树协议避免回路的产生,同时允许存在后备路径。交换机的工作特性交换机的每一个端口所连接的网段都是一个独立的冲突域。交换机所连接的设备仍然在同一个广播域内,也就是说,交换机不隔绝广播(惟一的例外是在配有VLAN的环境中)。交换机依据帧头的信息进行转发,因此说交换机是工作在数据链路层的网络设备(此处所述交换机仅指传统的二层交换设备

  • 修改网页自定义字体的CSS代码+图文教程

    HI,五一玩的怎么样?除了人山人海,高速堵车,高铁全是人之外其他都还好啦,是不是,哈哈哈~~~好了,不闹了,在假期有朋友问我,想要修改网页的字体怎么办?怎么更换网页的字体,又如何引用自定义字体呢?其实很简单,今天简单写个教程,需要能给小白一丢丢的帮助吧。首页我们要引用字体文件代码,代码参考如下:@font-face {     font-family: 'talklee';     font-display: swap;     src: url('./font/talklee.eot');     src: url('./font/talklee.eot?#iefix') format('embedded-opentype'),          url('./font/talklee.woff2') format('woff2'),        url('./font/talklee.woff') format('woff'

  • 探究新的 Solidity 0.8 版本

    译文出自:登链翻译计划[1]译者:翻译小组[2]校对:Tiny熊[3]我们离Solidity1.0的发布越来越近了(当然除非0.9之后是0.10)。Solidity0.8[4]在0.7发布[5]之后仅5个月就发布了!登链社区正在同步翻译Solidity0.8的文档[6]今天我们就来探讨一下如何把合约迁移升级到0.8版本......尤达宝宝发布0.8新功能和如何使用我们来看看两个大的新功能:集成的SafeMath和新的错误处理。1.集成SafeMathSafeMathMeme没错,你不需要再导入OpenzeppelinSafeMath[7]了。最重要的是,你不需要做任何事情就可以激活Solidity集成的SafeMath。只要写上a+b,就会在溢出时自动回退交易。你可能会在Remix等工具中看到如下错误提示,因为0.8还没有完全支持。比如溢出还没有给出确切的原因。transacttoSolidity08.testerrored:VMerror:revert.revert 复制但这种情况在未来应该会有所改变。如果你确实就希望代码能够溢出呢?还是非常在意Gas费了?则通过unchecked形

  • 重磅,腾讯发布最新开源jdk!

    Kona是由腾讯专业JVM技术团队维护开发的,基于OpenJDK的,提供长期支持并按季度更新的JDK发行版本。Kona目前作为默认JDK应用于腾讯云业务场景及其他Java应用场景。Kona基于OpenJDK,同时提供了更多的功能拓展及维护。通过腾讯Kona,用户可以获得更为先进的功能及性能优化,提高用户和开发者的使用体验。目前,腾讯Kona仅支持Linuxx86-64位系统.使用说明简介TencentKona-8支持以下特性:DefaultCDSArchive提高启动速度.JavaFlightRecorder采集java应用程序的诊断信息.DefaultCDSArchiveTencentKona默认打开DefaultCDSArchive功能,用户可以通过以下启动标志关闭该功能:java-Xshare:off 复制JavaFlightRecorder(JFR)TencentKona默认关闭JFR功能,用户可通过以下步骤使用"JFR使用步骤使用以下标志启动javajava-XX:+FlightRecorder 复制当应用程序运行时,使用以下命令采集JFR数据jcmd<you

  • Android 滑动渐变背景Toolbar、点击置顶ScrollView

    效果图如下: 点击置顶ScrollView 这个置顶是滑动的置顶,不包括外层布局。 好了,效果图看到了,你有没有动力开始写代码呢? 创建一个SlideLayoutDemo的项目 然后在res下新建一个network_security_config.xml 里面的代码很少,如下<?xmlversion="1.0"encoding="utf-8"?> <network-security-config> <base-configcleartextTrafficPermitted="true"/> </network-security-config>复制然后进入AndroidManifest.xml 增加了网络权限和http访问许可在app的build.gradle中添加相关的依赖先增加DataBind的使用 dataBinding{ enabled=true }复制 //GoogleMaterial控件,以及迁移到AndroidX下一些控件的依赖 implementation&

  • AOP方式代码控制多数据源切换

    版权声明:本文为博主原创文章,遵循CC4.0BY-SA版权协议,转载请附上原文出处链接和本声明。本文链接:https://blog.csdn.net/qq_37933685/article/details/80527461个人博客:https://suveng.github.io/blog/​​​​​​​AOP方式代码控制多数据源切换要想控制多数据源,必须继承spring提供的一个接口类重写里面AbstractRoutingDataSource的determineCurrentLookupKey()这里需要返回Map<Object,Object>targetDataSources的key,那么在spring配置一个bean吧,当然也可以写死,或者new一个对象,但是spring还是推荐用配置.注意,为什么会知道呢?也是百度和看了一下AbstractRoutingDataSource的源码的那么就需要配置spring了如下,我这里配置一个主库和两个从库,mysql怎么配置主从复制?上面一篇已经说明了看下面配置spring-cfg.xml<?xmlversion=&quo

  • Linux OOM一二三

    Linux开发一般会遇到“/proc/sys/vm/overcommit_memory”,即文件/etc/sysctl.conf中的vm.overcommit_memory,Overcommit的意思如同其字面意思,即进程可申请超出可用内存大小的内存(对进程而言实为虚拟内存,一个进程占用的虚拟内存空间通常比物理空间要大,甚至可能大许多)。overcommit_memory有三种取值(注:overcommit_memory并不控制OOM,是否开启OOM由panic_on_oom控制):overcommit_memory取值含义0系统默认值。在程序请求分配内存,比如C++程序调用malloc或new时,先检查是否有足够的内存。如果没有足够满足请求的内存,则分配请求失败。1启用Overcommit,即进程可申请超出CommitLimit大小的内存。2关闭Overcommit,即申请的内存大小不能超过CommitLimit。行为和/proc/sys/vm/overcommit_ratio的值相关,/proc/sys/vm/overcommit_ratio的默认值为50。 权威参考:https

  • react dva如何获取被form包裹的子组件函数

    工作上遇到个问题一对父子组件,如何获取子组件里的函数方法,网上的方法有很多,最常用的是添加ref,通过this.refName.fun便可获取该子组件里的函数.这里要说的是,在使用antd蚂蚁金服的时候,如果子组件被一个form包裹着,如何获取此时子组件里的方法?如果通过上述方法是获取不到相关的函数名的,需要这样写:constRentEquipment2=Form.create({withRef:true})(RentEquipment); exportdefaultRentEquipment2;复制加上withRef:true,它的默认值是false,[withRef](Boolean):Iftrue,storesareftothewrappedcomponentinstanceandmakesitavailableviagetWrappedInstance()method.Defaultvalue:false如果是true的话,会把这个ref的实例包裹起来,并使之有效.参考:https://github.com/reactjs/react-redux/blob/master/doc

  • 每天3分钟,重学ES6-ES12(十九)Proxy-Reflect

    theme:juejin持续创作,加速成长!这是我参与「掘金日新计划·6月更文挑战」的第32天,点击查看活动详情每天3分钟,重学ES6-ES12文章汇总 监听对象的操作我们先来看一个需求:有一个对象,我们希望监听这个对象中的属性被设置或获取的过程 通过我们前面所学的知识,能不能做到这一点呢?其实是可以的,我们可以通过之前的属性描述符中的存储属性描述符来做到;这段代码就利用了前面讲过的Object.defineProperty的存储属性描述符来对属性的操作进行监听。```jsconstobj={name:"why",age:18} Object.defineProperty(obj,"name",{get:function(){console.log("监听到obj对象的name属性被访问了")},set:function(){console.log("监听到obj对象的name属性被设置值")}})***但是这样做有什么缺点呢?** *首先,Object.defineProperty设计的初衷,不是为了去监

  • T 泛型转换

    T为左值 result=(T)Convert.ChangeType(o,typeof(T));

  • helm安装ingress

    ​ helm安装ingress ​一、安装Helm #wgethttps://get.helm.sh/helm-v3.3.4-linux-amd64.tar.gz ​ #tart-zxvfhelm-v3.3.4-linux-amd64.tar.gz ​ #mvlinux-amd64/helm/usr/local/bin/helm ​ #helmversion version.BuildInfo{Version:"v3.3.4",GitCommit:"a61ce5633af99708171414353ed49547cf05013d",GitTreeState:"clean",GoVersion:"go1.14.9"} 复制     二、下载ingress #mkdiringress&&cdingress #新建仓库 #helmrepoaddingress-nginxhttps://kubernetes.github.io/ingress-nginx ​ #helmpullingressingress-nginx/ingress-nginx #tar-

  • 扩增子分析QIIME2-4分析实战Moving Pictures

    本示例的的数据来自文章《Movingpicturesofthehumanmicrobiome》,GenomeBiology2011,取样来自两个人身体四个部位五个时间点   进入环境 sourceactivateqiime2-2017.8 退出环境 sourcedeactivate   准备数据 #创建并进入工作目录 mkdir-pqiime2-moving-pictures-tutorialcdqiime2-moving-pictures-tutorial #下载实验设计(-O重命名下载的文件) wget-Osample-metadata.tsv https://data.qiime2.org/2017.6/tutorials/moving-pictures/sample_metadata.tsv ##上面一步下载失败,可尝试删除空文件并使用我建立的备份链接下载;否则跳过下面两行命令 rmsample_metadata.tsvwget http://bailab.genetics.ac.cn/markdown/sample-metadat

  • DP Help Jimmy POJ - 1661

     HelpJimmy"是在下图所示的场景上完成的游戏。  场景中包括多个长度和高度各不相同的平台。地面是最低的平台,高度为零,长度无限。 Jimmy老鼠在时刻0从高于所有平台的某处开始下落,它的下落速度始终为1米/秒。当Jimmy落到某个平台上时,游戏者选择让它向左还是向右跑,它跑动的速度也是1米/秒。当Jimmy跑到平台的边缘时,开始继续下落。Jimmy每次下落的高度不能超过MAX米,不然就会摔死,游戏也会结束。 设计一个程序,计算Jimmy到底地面时可能的最早时间。   思路:jimmy从一点开始下落,落到一个平台上时,他可以选择从左边下落,也可以从右边下落,因为可能存在大量重复的情况,用一个数组记录每种计算过的状态。 假如要从可以从一个平台的左边下落到下一个平台,那么a[i].x1>a[i-1].x1&&a[i].x1<=a[i-1].x2, x1,x2分别是平台左右两边的横坐标。 分情况讨论: 1.H[i]-H[m]>ma dp[i][0]=inf,dp[i][1]=inf

  • Xcode8打包上传后构建版本消失问题

      升级Xcode8之后,就是上传成功后,构建文件莫名消失,百分之百就是那个隐私权限没有设置。 iOS 10开始对隐私权限更加严格,如果你不设置就会直接崩溃,现在很多遇到崩溃问题了,一般解决办法都是在info.plist文件添加对应的Key-Value就可以了。 详情可参考:http://www.cnblogs.com/caodedi-88/p/6265301.html  

  • 动目标指示MTI和动目标检测MTD

    1.运动目标指示(MTI) 由一个CPI内的连续M个脉冲回波经过相干解调后的基带数据,形成的一个二维数据矩阵。二维数据矩阵中的每一列都对应于对一个脉冲回波的连续釆样,即连续的距离单元。列中的每一个元素都是一个复数,代表一个距离单元的实部和虚部(I和Q)分量。因此,二维数据矩阵中的每一行代表对同一距离单元的一连串脉冲测量。    MTI处理器对慢时间数据序列执行线性滤波处理,以抑制数据中的杂波分量。下图描述了MTI的处理过程。MTI处理所需要的滤波器类型也可以由下图来理解    上述MTI处理中只能给出在感兴趣的距离单元中是否存在目标的判决信息,并没有提供任何关于目标多普勒频率的估计信息,这也是为什么叫做动目标指示MTI的原因,也就是MTI的本质作用在于指示目标有无。更确切地说,MTI地目的是通过某种滤波手段,将其中的目标信息保留,而将静态杂波信息予以剔除。 实际上,脉冲对消器被用来设计为MTI的一种手段,因为运动目标一直在运动,所以回波信号的相位信息一直在变化,这就导致了采用对消的手段可以将其中运动的目标检测出来,而将静态杂波剔除掉。常用的脉

  • Spring实例化bean的三种方式

    1.用构造器来实例化 <bean id="hello2" class="com.hsit.hello.impl.ENhello" />   2.使用静态工厂方法实例化     <bean id="hello1" class="com.hsit.hello.impl.CHhello" factory-method="createInstance" lazy-init="true">         <!-- setter注入 -->         <property name="msg" value="哈哈">         </prop

  • Oracle学习笔记2

    截断表:truncate table 表名  时间操作 一个月的第一天 SELECTto_date(to_char(SYSDATE,'yyyy-mm')||'-01','yyyy-mm-dd')FROMdual 一年的第一天 SELECTto_date(to_char(SYSDATE,'yyyy')||'-01-01','yyyy-mm-dd')FROMdual 季度的第一天 SELECTto_date(to_char(SYSDATE,'yyyy-')||lpad(floor(to_number(to_char(SYSDATE,'mm'))/3)*3+1,2,'0')||'-01','yyyy-mm-dd')FROMdual 上个月的最后一天 SELECTtrunc(last_day(add_months(SYSDATE,-1)))+1-1/24/60/60FROMdual 本年的最后一天 SELECTtrunc(last_day(to_date(to_char(SYSDATE,'yyyy')||'-12-01','yyyy-mm-dd')))+1-1/2

  • u-boot-2014.10移植(9)nand.yaff

    支持nandyaffs支持   添加宏#defineCONFIG_CMD_NAND_YAFFS即可

相关推荐

推荐阅读