指针和指针应用的区别

2023-11-13

 转自:https://www.cnblogs.com/x_wukong/p/5712345.html

         http://blog.sina.com.cn/s/blog_673ef8130100imsp.html

   指针参数的传递,传递的是对指针的拷贝值,如果在函数中对指针的值进行修改,不会影响到主函数中的值,因为在函数执行完成后,执行这个函数产生局部变量的栈区就会清空..  

  指针传递参数本质上是值传递的方式,它所传递的是一个地址值。值传递过程中,被调函数的形式参数作为被调函数的局部变量处理,即在栈中开辟了内存空间以存放由主调函数放进来的实参的值,从而成为了实参的一个副本。值传递的特点是被调函数对形式参数的任何操作都是作为局部变量进行,不会影响主调函数的实参变量的值。(这里是在说实参指针本身的地址值不会变)

   引用传递相当于编译器对参数取地址然后传递(换句话说就是传递的是存储参数的地址(指针))然后对函数中所有参数涉及到的地方取间接寻址(*)

int swap(int &a,int &b)
{
    int temp=a;//temp=*a;
    a=b;//*a=*b;
    b=temp;//*b=temp;
}
int p,q;
swap(p,q);//p实际传的是p的地址,q同理

 

  而在引用传递过程中,被调函数的形式参数虽然也作为局部变量在栈中开辟了内存空间,但是这时存放的是由主调函数放进来的实参变量的地址(int &a的形式)。被调函数对形参的任何操作都被处理成间接寻址,即通过栈中存放的地址访问主调函数中的实参变量。正因为如此,被调函数对形参做的任何操作都影响了主调函数中的实参变量。

引用传递和指针传递是不同的,虽然它们都是在被调函数栈空间上的一个局部变量,但是任何对于引用参数的处理都会通过一个间接寻址的方式操作到主调函数中的相关变量。而对于指针传递的参数,如果改变被调函数中的指针地址,它将影响不到主调函数的相关变量。如果想通过指针参数传递来改变主调函数中的相关变量,那就得使用指向指针的指针,或者指针引用。

为了进一步加深大家对指针和引用的区别,下面我从编译的角度来阐述它们之间的区别:

程序在编译时分别将指针和引用添加到符号表上,符号表上记录的是变量名及变量所对应地址。指针变量在符号表上对应的地址值为指针变量的地址值,而引用在符号表上对应的地址值为引用对象的地址值。符号表生成后就不会再改,因此指针可以改变其指向的对象(指针变量中的值可以改),而引用对象则不能修改。

最后,总结一下指针和引用的相同点和不同点:

★相同点:

●都是地址的概念;

指针指向一块内存,它的内容是所指内存的地址;而引用则是某块内存的别名。

★不同点:

●指针是一个实体,而引用仅是个别名;

●引用只能在定义时被初始化一次,之后不可变;指针可变;引用“从一而终”,指针可以“见异思迁”;

●引用没有const,指针有const,const的指针不可变;(具体指没有int& const a这种形式,而const int& a是有     的,  前者指引用本身即别名不可以改变,这是当然的,所以不需要这种形式,后者指引用所指的值不可以改变)

●引用不能为空,指针可以为空;

●“sizeof 引用”得到的是所指向的变量(对象)的大小,而“sizeof 指针”得到的是指针本身的大小;

●指针和引用的自增(++)运算意义不一样;

●引用是类型安全的,而指针不是 (引用比指针多了类型检查

一、引用的概念

引用引入了对象的一个同义词。定义引用的表示方法与定义指针相似,只是用&代替了*。
例如: Point pt1(10,10);
Point &pt2=pt1; 定义了pt2为pt1的引用。通过这样的定义,pt1和pt2表示同一对象。
需要特别强调的是引用并不产生对象的副本,仅仅是对象的同义词。因此,当下面的语句执行后:
pt1.offset(2,2);
pt1和pt2都具有(12,12)的值。
引用必须在定义时马上被初始化,因为它必须是某个东西的同义词。你不能先定义一个引用后才
初始化它。例如下面语句是非法的:
Point &pt3;
pt3=pt1;
那么既然引用只是某个东西的同义词,它有什么用途呢?
下面讨论引用的两个主要用途:作为函数参数以及从函数中返回左值。

二、引用参数

1、传递可变参数
传统的c中,函数在调用时参数是通过值来传递的,这就是说函数的参数不具备返回值的能力。
所以在传统的c中,如果需要函数的参数具有返回值的能力,往往是通过指针来实现的。比如,实现
两整数变量值交换的c程序如下:
void swapint(int *a,int *b)
{
int temp;
temp=*a;
a=*b;
*b=temp;
}

使用引用机制后,以上程序的c++版本为:
void swapint(int &a,int &b)
{
int temp;
temp=a;
a=b;
b=temp;
}
调用该函数的c++方法为:swapint(x,y); c++自动把x,y的地址作为参数传递给swapint函数。

2、给函数传递大型对象
当大型对象被传递给函数时,使用引用参数可使参数传递效率得到提高,因为引用并不产生对象的
副本,也就是参数传递时,对象无须复制。下面的例子定义了一个有限整数集合的类:
const maxCard=100;
Class Set
{
int elems[maxCard]; // 集和中的元素,maxCard 表示集合中元素个数的最大值。
int card; // 集合中元素的个数。
public:
Set () {card=0;} //构造函数
friend Set operator * (Set ,Set ) ; //重载运算符号*,用于计算集合的交集 用对象作为传值参数
// friend Set operator * (Set & ,Set & ) 重载运算符号*,用于计算集合的交集 用对象的引用作为传值参数
...
}
先考虑集合交集的实现
Set operator *( Set Set1,Set Set2)
{
Set res;
for(int i=0;i<Set1.card;++i)
for(int j=0;j>Set2.card;++j)
if(Set1.elems[i]==Set2.elems[j])
{
res.elems[res.card++]=Set1.elems[i];
break;
}
return res;
}
由于重载运算符不能对指针单独操作,我们必须把运算数声明为 Set 类型而不是 Set * 。
每次使用*做交集运算时,整个集合都被复制,这样效率很低。我们可以用引用来避免这种情况。
Set operator *( Set &Set1,Set &Set2)
{ Set res;
for(int i=0;i<Set1.card;++i)
for(int j=0;j>Set2.card;++j)
if(Set1.elems[i]==Set2.elems[j])
{
res.elems[res.card++]=Set1.elems[i];
break;
}
return res;
}

三、引用返回值

如果一个函数返回了引用,那么该函数的调用也可以被赋值。这里有一函数,它拥有两个引用参数并返回一个双精度数的引用:
double &max(double &d1,double &d2)
{
return d1>d2?d1:d2;
}
由于max()函数返回一个对双精度数的引用,那么我们就可以用max() 来对其中较大的双精度数加1:
max(x,y)+=1.0;

 

注:int &a中的&本质就是“取地址”运算,在函数void swapint(int &a,int &b)中,&a要看成一个整体,看成是x的地址,故a就是x本身了

有区别,  
  无论你传值还是传指针,函数都会生成一个临时变量,  
  但传引用时,不会生成临时变量,  
   
  当你传值时,只可以引用值而不可以改变值,但传值引用时,可以改变值,  
  当你传指针时,只可以改变指针所指的内容,不可以改变指针本身,但传指针引用时,既可以改变指针所指的内容,又可以改变指针本身,  
   
  但传引用主要是它不生成临时变量,不进行返回值copy等,速度快。  

  数据结构的二叉排序树中有典型应用..

 

注:简单一点可以这么想,如果不用引用的话,被传递的参数本身是不能被修改的,  
  即使你传递的是指针,也只能修改指针指向的内容,不能修改指针本身。  
  如果要修改当前被传递的参数的话,要么再加一级指针,要么用引用。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

指针和指针应用的区别 的相关文章

  • Linux中三种引号(单引号、双引号、反引号)的区别

    1 双引号 保护特殊元字符和通配符不被shell解析 但是允许变量和命令的解析 以及转义符的解析 2 单引号 单引号内不允许任何变量 元字符 通配符 转义符被shell解析 均被原样输出 使用双引号或反斜杠转义可显示输出单引号 但是双引号和
  • 创建型设计模式之抽象工厂(Abstract Factory)模式

    定义 为创建一组相关或相互依赖的对象提供一个接口 而且无需指定他们的具体类 用意 客户端在不必指定产品的具体类型情况下 创建多个产品族中某个产品对象 定义图 参与者 抽象工厂 Creator 工厂方法核心 由一个接口或抽象类实现 具体工厂类
  • 【每日知识】点击下载按钮

    代码如下 methods OncilckUpload let link document createElement a 创建一个a标签 link style display none 将a标签隐藏 link href https api
  • $set在vue中的应用案例

    vue中this set在官方API中是这样说的 Vue set target propertyName index value 参数 Object Array target string number propertyName index
  • java api如何获取kafka所有Topic列表,并放置为一个list

    kafka内部所有的实现都是通过TopicCommand的main方法 通过java代码调用API TopicCommand main options 的方式只能打印到控制台 不能转换到一个list 下面讲解下如何转换为list 1 查看主
  • 三分钟快速搭建家纺行业小程序商城

    在互联网时代 越来越多的企业开始意识到小程序的重要性和价值 家纺行业也不例外 许多家纺企业开始关注和投入小程序商城的建设 然而 对于大多数家纺企业来说 搭建一个小程序商城可能会显得十分困难和复杂 但是 通过乔拓云平台 你只需要三分钟 就可以
  • 【Stm32野火】:野火STM32F103指南者开发板烧写官方示例程序LCD无法点亮?LCD示例程序无法使用?

    项目场景 大家好 最近在使用野火STM32F103指南者开发板的时候发现官方的示例程序LCD驱动代码居然无法直接驱动LCD点亮 这让我百思不得其解 以下就是我的踩坑填坑的过程 希望对大家有所帮助 野火官方资料下载文档链接 野火STM32F1
  • 计算机核心期刊排名及投稿信息

    1 计算机学报 北京 中国计算机学会等 2 软件学报 北京 中国科学院软件研究所 3 计算机研究与发展 北京 中国科学院计算技术研究所等 4 自动化学报 北京 中国科学院等 5 计算机科学 重庆 国家科技部西南信息中心 6 控制理论与应用
  • [Python图像处理] 三十七.OpenCV直方图统计两万字详解(掩膜直方图、灰度直方图对比、黑夜白天预测)

    该系列文章是讲解Python OpenCV图像处理知识 前期主要讲解图像入门 OpenCV基础用法 中期讲解图像处理的各种算法 包括图像锐化算子 图像增强技术 图像分割等 后期结合深度学习研究图像识别 图像分类应用 希望文章对您有所帮助 如
  • 线程池源码分析(一)

    最近在阅读 阿里巴巴Java开发手册 的时候 书中有这么一段话 线程池这块理解不是很深 今天就抽时间重新学习一遍 对于书中的问题分析完成后答案便一目了然 创建线程池的一个方式 ExecutorService e Executors newF
  • 三维重建_COLMAP安装、使用和参数说明(翻译自官方文档)

    近期因为想要入选学校某位很厉害的老师的某个项目 布置的小任务就是先把colmap以及openMVS跑一跑 我就记录了一下学习的经过 一 Ubuntu上源码编译colmap 参考网址 https colmap github io instal
  • 单片机串口控制树莓派3B播放HDMI视频,omxplayer,

    使用树莓派3B通过HDMI播放视频 并且使用串口去控制播放哪个视频 1 问题解耦 单片机串口控制树莓派3B播放视频 树莓派播放视频 单片机串口传参控制树莓派 树莓派播放视频 树莓派播放视频 并且能用串口这种简单的通信方式去控制 应该是需要安
  • java实现写大量数据到文件中

    生成 txt文件 生成 csv文件 生成 xls文件 import java io BufferedWriter import java io File import java io FileOutputStream import java
  • 【缓存】缓存,这么用才真正达到缓存的效果

    1 概述 转载 https zhuanlan zhihu com p 62508629 一 什么是缓存 平常的开发项目中 多多少少都会使用到缓存 因为一些数据我们没有必要每次查询的时候都去查询到数据库 一个形象的比喻 数据库是人的身体 缓存
  • 序列比对算法-计算生物学

    1 序列比对指将两个或多个序列排列在一起 标明其相似之处 序列中可以插入间隔 通常用短横线 表示 对应的相同或相似的符号 在核酸中是A T 或U C G 在蛋白质中是氨基酸残基的单字母表示 排列在同一列上 这一方法常用于研究由共同祖先进化而
  • CSS 3D转换——transform 属性的 rotatex() 方法和 rotatey() 方法

    目录 CSS 3D转换 浏览器支持 转换属性 3D Transform方法 常用方法 rotatex 方法 rotatey 方法 结语 CSS 3D转换 CSS3 允许我们使用 3D 转换来对元素进行格式化 浏览器支持 表格中的数字表示支持
  • 无线局域网下的远程控制、文件传输以及代理设置[Windows

    需求 在同一个路由器连接的局域网下 Ubuntu通过Windows端上网 Windows端远程控制Ubuntu系统 主机 Windows10 被操控端 Ubuntu18 04 在Windows方下载一个客户端 如Termius 远程控制和操
  • sql注入(报错注入)适用于union无法使用的情况

    extractvalue函数原理 这是一个对xml文件进行查询的函数 它的作用是 会从目标xml文件中返回所包含查询值的字符串 标准语法为 extractvalue XML document Xpath string extractvalu
  • for循环实现1-100之间偶数和

    package com itheima 04 需求 求出1 100之间偶数和 分析 A 定义求和变量 初始化值是0 B 获取1 100之间的数据 用for循环实现 C 把获取到的数据进行判断 看是否是偶数 如果是 就累加 D 输出求和结果
  • kernel:关于linux内核重要文件的基本描述

    linux Makefile 文件 这个Makefile文件的主要作用是指示make程序最终使用独立编译连接成的tools 目录中的build执行程序将所有内核编译代码连接和合并成一个可运行的内核映像文件 image 具体是对 boot 中

随机推荐

  • 协处理器cp15

    CP15访问CP15寄存器的指令 在基于ARM的嵌入式应用系统中 存储系统通常是通过系统控制协处理器CP15完成的 ARM处理器使用协处理器CP15的寄存器来控制cache 极高速缓存 TCM 高速缓存 和存储管理 CP15包含16个32位
  • anaconda的安装和常用指令

    1 下载anaconda之后 首先打开anaconda prompt 输入 conda version获取当前anaconda的版本 有可能会出现 首先要清理所有的包 conda clean packages tarballs 可以Win
  • 如何控制Spring bean的生命周期

    先了解下Spring bean的生命周期 创建 初始化 销毁 这对读懂Spring源码十分有帮助 控制Spring bean的生命周期有3种方式 下面分别用代码展示 方式一 Bean 注解上手动指定bean的初始化方法和销毁方法 Confi
  • 操作系统 存储管理 分页分段

    操作系统 存储管理 分页分段 分页存储管理 是将一个进程的逻辑地址空间分成若干个大小相等的片 称为页面或页 并为各页进行编号 从0开始 分页地址中的地址结构如下 页表实现了从页号到物理块号的地址映像 通过查找该表 即可找到每页在内存中的物理
  • c语言在线翻译器,【C语言】【window】--在线翻译器.doc

    C语言 Windows 在线翻译器 01 程序简介 程序名称 编译器 vs2010 其它也可以 程序大小 10K 文件包括 exe skinh she SkinH dll msvcr100 dll 程序界面 02 任务说明 光影队 任务 L
  • 自定义JSP中的Taglib标签之四自定义标签中的Function函数

    Java代码如下 自定义JSP中的Taglib标签之四自定义标签中的Function函数 package org lxh taglib import java util List public class FunctionTag publi
  • 报错"your evaluation license has expired, pycharm will now exit"

    1 修改C Windows System32 drivers etc hosts文件 将 0 0 0 0 account jetbrains com 添加到hosts文件的最后一行2 访问 http idea lanyus com 获取注册
  • NIO下载超大文件(支持20个G)

    服务端 nio将文件流写入response author zhanghp2017he foxmail com date 2022 8 22 param response return void exception RequestMappin
  • 【LeetCode75】第二十九题 删除链表的中间节点

    目录 题目 示例 分析 代码 题目 示例 分析 给我们一个链表 让我们把链表中间的节点删了 那么最直观最基础的办法是遍历两边链表 第一遍拿到链表长度 第二次把链表中间节点删了 这个暴力做法我没事过 不过貌似是可以解决问题的 所以我觉得这题的
  • React-router 5.0 利用高阶函数实现路由嵌套(web)

    如今 react router 已经升级到v5 0版本 v4 0版本做了较大的改革 代码中依然使用v3 0版本的写法 于是准备整改为v4 0以上版本 遇到了很多坑 于是做个笔记 首先 对比一下 v3 0 和 v4 0 版本 v4 0提供了r
  • librdkafka consumer封装的一点总结

    关于librdkafka producer可以看这里 consumer相较于producer需要注意的问题就少得多了 首先是初始化 string errstr unique ptr
  • 移植3- uboot之nandflash驱动移植

    2014 8 18 在上一篇文章中 我们已经将uboot启动起来了 但是如何将uboot spl搞到nandflash中去 这样可以拨动拨码开关选择nandflash启动 就可以从nandflash启动了呢 因此需要在uboot中实现nan
  • hooks api 详细demo

    本文所有代码demo https stackblitz com edit react hooks memo gwv9c6 file index js overview deep div How do React hooks really w
  • MYSQL group by后删除每个分组中的重复数据,只保留最新一条

    一 需求 MYSQL group by后删除每个分组中的重复数据 只保留最新一条 二 实现 获取 group by后每个分组中除去最新一条记录的其他重复数据 SELECT FROM test WHERE test user id IN 按照
  • 用python写一个猜数字小游戏

    需要用到python的random库来随机生成一个需要用户猜的数字 之后判断用户输入的数字 与生成的数字比较 并告知用户 先随机生成一个随机数 num random randint 1 49 随机生成一个1 49的数字 判断用户输入的数字
  • 数据结构-排序算法比较(内部排序)

    内部排序算法的比较 时间复杂度 最坏 最好 平均 注 直接插入 O n2 O n O n2 折半插入与之类似 冒泡 O n2 O n O n2 简单选择 O n2 与初态无关 希尔 O n1 3 具体不确定 快排 O n2 O nlog2n
  • transformer模型学习路线

    Transformer学习路线 完全不懂transformer 最近小白来入门一下 下面就是本菜鸟学习路线 Transformer和CNN是两个分支 因此要分开学习 Transformer是一个Seq2seq模型 而Seq2seq模型用到了
  • 字符串 验证回文串

    LC 验证回文串 Swift func isPalindrome s String gt Bool 字母转小写 let str s lowercased 去除标点等特殊字符 只留字母 let pattern a z let regex tr
  • WPF 控件库Live Charts 折线图多折线比较问题处理

    使用Live Charts功能对比多条折线时当Label不是一一对应时会发现折线无法对比如 Labels List
  • 指针和指针应用的区别

    转自 https www cnblogs com x wukong p 5712345 html http blog sina com cn s blog 673ef8130100imsp html 指针参数的传递 传递的是对指针的拷贝值