概念

  • 指针从本质上讲是一个变量,变量的值是另一个变量的地址,指针在逻辑上是独立的,它可以被改变的,包括指针变量的值(所指向的地址)和指针变量的值对应的内存中的数据(所指向地址中所存放的数据)。
  • 引用从本质上讲是一个别名,是另一个变量的同义词,它在逻辑上不是独立的,它的存在具有依附性,所以引用必须在一开始就被初始化(先有这个变量,这个实物,这个实物才能有别名),而且其引用的对象在其整个生命周期中不能被改变,即自始至终只能依附于同一个变量(初始化的时候代表的是谁的别名,就一直是谁的别名,不能变)。

区别

指针 变量,独立,可变,可空,替身,无类型检查
引用 别名,依赖,不变,非空,本体,有类型检查
  • 指针参数传递本质上是值传递,它所传递的是一个地址值。值传递过程中,被调函数的形式参数作为被调函数的局部变量处理,会在栈中开辟内存空间以存放由主调函数传递进来的实参值,从而形成了实参的一个副本(替身)。值传递的特点是,被调函数对形式参数的任何操作都是作为局部变量进行的,不会影响主调函数的实参变量的值(形参指针变了,实参指针不会变)。

  • 引用参数传递过程中,被调函数的形式参数也作为局部变量在栈中开辟了内存空间,但是这时存放的是由主调函数放进来的实参变量的地址。被调函数对形参(本体)的任何操作都被处理成间接寻址,即通过栈中存放的地址访问主调函数中的实参变量(根据别名找到主调函数中的本体)。因此,被调函数对形参的任何操作都会影响主调函数中的实参变量。

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

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

以上内容来源网络

如何使用

如果我们编程只是为了做一些简单的工作,不想在技术上有什么质的突破,那么使用指针就够了。这样做的问题就是,你写的代码很容易出bug。可是,如果我们想要对c++有更深的了解,那么一定要区分指针传参与引用传参的区别。

使用指针传递参数,是为了避免拷贝副本,从而提高程序执行效率,大所数初学者(也包括我)都习惯使用指针传递参数,因为还没有建立起引用的概念,我们以为指针就是引用,殊不知,引用的内涵比指针更丰富。因为用的少,所以对引用的概念懵懵懂懂。其实有经验的程序员在传递参数时很少使用指针。下面通过代码来说明我们为什么要使用引用传参,放弃指针传参。

  • 首先定义一个结构体
struct ST
{public:int num;string name;ST(int num, string name){this->num = num;this->name = name;}void putInfo(){cout << "学号:" << num << endl;cout << "姓名:" << name << endl;}
};

1.使用指针传参

void dealProcess(ST* st)
{ST *newST =new ST(320, "小明");st = newST;//为临时指针变量赋予了新值,已和输入脱离了联系。
}int main()
{int num = 1;ST st1(310, "小红");dealProcess(&st1);st1.putInfo();system("pause");return 0;
}
  • 输出结果

使用指针传参,想返回处理后的结果,但是我们得到的结果却和预想的不一致。因为在处理的过程中,形参的地址发生了变化,和输入脱离了联系。

  • 正确的写法:
void dealProcess(ST* st)
{ST *newST =new ST(320, "小明");*st = *newST;
}
  • 严谨的写法(但不简洁)
void dealProcess(ST* const st)//指定形参为常量指针,不能修改值
{ST *newST =new ST(320, "小明");*st=*newsT;st = newST;    //编译错误,不允许修改常量
}

void dealProcess(ST* const st)等价于void dealProcess(ST* st const)

2.既严谨又简洁的写法,使用引用

void dealProcess(ST& st)
{ST newST(320, "小明");st = newST;    &st=&newsT;//编译错误,不允许改变输入的地址
}
int main()
{int num = 1;ST st1(310, "小红");dealProcess(st1);st1.putInfo();system("pause");return 0;
}

3.如果仅仅是使用输入的值,应该限定输入为常量

  • 首选是使用引用
void dealProcess(const ST& st)
{ST newST(0,"");newST.putInfo();//输入的值不允许被改变st = newST;  //编译错误,只允许使用输入,不允许改变输入的值  &st = &newsT;//编译错误,不允许改变输入的地址//使用输入的值,newST = st;newST.putInfo();
}
int main()
{int num = 1;ST st1(310, "小红");dealProcess(st1);system("pause");return 0;
}

  • 如果一定要使用指针,等价代码如下
void dealProcess(const ST* const st)
{ST newST(0,"");newST.putInfo();//使用输入的值newST = *st;newST.putInfo();
}
int main()
{int num = 1;ST st1(310, "小红");dealProcess(&st1);system("pause");return 0;
}

c++ 引用传参和指针传参的区别相关推荐

  1. 【C语言进阶】⑤关于数组传参和指针传参辨析

    文章目录 一.数组 1.1.一维数组 1.2.二维数组 1.3.指针和数组 二.数组传参 2.1一维数组传参 2.2二维数组传参 2.3小结 三.指针传参 3.1一维指针传参 3.3二级指针传参 四. ...

  2. 指针-数组传参,指针传参

    目录 数组传参 一维数组 二维数组 指针传参 一级指针 二级指针 一个特殊的二级指针 数组传参 一维数组 我们把传入一维数组时输入的是数组名,数组名是一个指向首元素的指针 那么在函数接收时,只需要保证 ...

  3. c一:指针引用(int * p )和指针(int * q)的区别

    #include <iostream>using namespace std;int g = 300;void print(int p, int q) {cout << p & ...

  4. 一篇让你弄明白C语言指针传参和数组传参~

    文章目录 前言 ⭐️指针传参和数组传参 ⭐️一维数组传参 ⭐️一级指针传参 ⭐️一道经典的指针传参相关题目 ⭐️二维数组传参 ⭐️函数指针!!! ⭐️一个有趣的代码!(*(void( * )())0) ...

  5. 【C语言】指针进阶 - 指针数组 数组指针 数组指针传参 函数指针 指向函数指针数组的指针

    目录 一.字符指针 一道题 二. 指针数组 解引用打印数组元素 &数组名 数组名 字符指针初始化 三.数组指针 取数组地址-放在数组指针里 类型 数组指针的使用 二维数组传参 判断 四.数组参 ...

  6. C/C++ 一维数组的传参/一级指针的传参 二维数组的传参/二级指针的传参 三维数组的传参/三级指针的传参 方法总结分析终极篇

    序 最近复习c/c++数组的传参,发现了一些问题,下面是一些总结和思考 正文 一维数组的传参/一级指针的传参/普通指针 在理解指针的基础上,一维数组的指针传递很简单,我们知道数组的数组名就是这个数组首 ...

  7. python 传参 数组_python传参为数组-女性时尚流行美容健康娱乐mv-ida网

    女性时尚流行美容健康娱乐mv-ida网 mvida时尚娱乐网 首页 美容 护肤 化妆技巧 发型 服饰 健康 情感 美体 美食 娱乐 明星八卦 首页  > 高级搜索 python 替换字符 为 空 ...

  8. PHP基础传参,PHP四种传参方式

    test1界面: testPHP //第一种设置传参方式,通过cookie setcookie('my','yefeng'); //第二种传参方式,通过设置服务器session值传递参数 sessio ...

  9. python 元组传参 *args 字典传参 **kwargs 的用法

    python 元组传参 *args 字典传参 **kwargs 的用法 # 元组参数 def func_arg(*args):print("args:", args) func_a ...

最新文章

  1. 分享几个用 Python 给图片添加水印的方法,简单实用
  2. (五)我的JavaScript系列:JavaScript的糟粕
  3. python 加注拼音-又一个奇葩要求,Python是如何将“中文”转“拼音”的?
  4. 安装python 的包控制mysql的Python脚本与执行系统命令的Python脚本
  5. 成功解决A value is trying to be set on a copy of a slice from a DataFrame. Try using .loc[row_indexer,co
  6. 【C++基础】C++11的noexcept声明符 与 异常传播
  7. 云计算-从基础到应用架“.NET研究”构系列-云计算的演进
  8. vc++源码免杀特殊技巧
  9. 更换用户目录后conda环境配置
  10. mysql8下的密码过期问题以及navicat登录mysql报错的问题
  11. 五子棋c语言代码光标,c语言写的鼠标操作的五子棋游戏,欢迎观赏!
  12. 微信多开软件(Java版)
  13. Axure 8.0/9.0 注册码 激活码 授权码 License
  14. MaixII-Dock(v831)学习笔记——初识v831
  15. DEM数据知识介绍-数字高程模型
  16. 软件测试简历编写以及软件测试面试题大全(接口、自动化测试面试题)赶快收藏
  17. 神经网络中的BN操作(常见正则化处理)
  18. argparse用于解析命令行参数
  19. c语言实现海龟爬行程序
  20. 云计算事故不断,企业上云如何避免事故导致重大损失?

热门文章

  1. 从一个数组循环每次拿五个出来放到另外一个数组
  2. 不同类型面膜特点及功效
  3. flutter代码规范配置
  4. OpenMV的pyb.USB_VCP().isconnected()状态异常
  5. 百元的价格,五星级的体验,尽在朗丽兹酒店
  6. 人形机器人促进人工智能技术发展
  7. linux常用命令-1备份压缩
  8. VisualBrush画刷
  9. 《微服务实战》微服务设计原则
  10. 并发和并行有什么区别?