既然有指针了,为什么 C++ 还搞个引用出来?

news/2024/11/16 22:41:29/

1. 对象的定义:

对象是指一块能存储数据并具有某种类型的内存空间;

一个对象a,它有值和地址&a,运行程序时,计算机会为该对象分配存储空间,来存储该对象的值,我们通过该对象的地址,来访问存储空间中的值;

2. 指针的定义

指针:它保存一个值(或 null)的地址,可以检索指向该地址处的值 。

指针定义时,可以不用初始化;

指针可以初始化为NULL,

指针的在初始化后, 其地址值仍可以改变, 用于存储另外一个地址;

指针p也是对象,它同样有地址&p和存储的值p,只不过,p存储的数据类型是数据的地址。

如果我们要以p中存储的数据为地址,来访问对象的值,则要在p前加解引用操作符"",即p。

3. 指针的常量和变量之分

对象有常量(const)变量之分,

既然指针本身是对象,那么指针所存储的地址也有常量和变量之分;

指针常量是指,指针这个对象所存储的地址是不可以改变的,

而指向常量的指针的意思是,不能通过该指针来改变这个指针所指向的对象。

4.引用

引用用于在程序的不同的部分使用两个以上的变量名指向同一块地址,

使得对其中任何一个变量的操作实际上都是对同一地址单元进行的。

引用的特点:

  1. 引用仅是变量的别名,而不是实实在在地定义了一个变量,因此引用本身并不占用内存,引用,表明上是为变量创建了第二个名字, 它的本质是一个指针,和目标变量的是同一个内存地址声明引用时,目标的存储状态不会改变;

  2. 引用在定义时,必须初始化, 且不能初始化为空;只有在引用申明时, “&” 才称作引用符,且放在类型名后面;其他时候出现的 “&”, 都是指 取地址操作符;。

  3. 引用只能在初始化的时候引用一次 ,不能更改为转而引用其他变量。

  4. 对引用进行操作,实际上就是对被引用的变量进行操作;

5. C++ 中为什么要有 “引用”

C++ 中引用的出现,最初是为了解决, 运算符重载的 问题;

假设没有引用,那么,用指针来operator overloading操作。 A operator +(const A *a, const A *_a);
那么使用的时候,&a + &b, 这样看起来不是那样简单明了。
引用解决C++运算符重载后代码美观的问题。

并且引用的 出现带来了 一个指针无法替代的特性: 引用临时对象;

引用在定义的时候必须就赋值,并且此后再也无法更改;

5.1 引用的特性

并且在实践中,使用指针,经常出现一下情况:

  1. 操作空指针
  2. 操作野指针
  3. 不知不觉中, 手动改变了指针的值,随后以为该指针正常,关键本人不知道;

为了设立一种机制, 保证上述三种情况的不发生, “ 引用”这个机制保证避免发生上述三种情况

引用特性:

  1. 引用不允许为空 (从而避免了操作空指针)
  2. 引用在定义的时候,就必须初始化(避免了操作 野指针)
  3. 一个引用 ,始终从一而终的指向他 初始化的那个对象 ( 避免了指针的值不会被修改)

5.2 引用作为函数参数

C++ 支持把引用作为参数传给函数, 这比传一般的参数更安全

(1)传递引用给函数与传递指针的效果是一样的。这时,被调函数的形参就成为原来主调函数中的实参变量或对象的一个别名来使用,所以在被调函数中对形参变量的操作就是对其相应的目标对象(在主调函数中)的操作。

(2)使用引用传递函数的参数,在内存中并没有产生实参的副本,它是直接对实参操作:

  1. 而使用一般变量传递函数的参数,当发生函数调用时,需要给形参分配存储单元,形参变量是实参变量的副本;
  2. 如果传递的是对象,还将调用拷贝构造函数。
  3. 因此,当参数传递的数据较大时,用引用比用一般变量传递参数的效率和所占空间都好。

(3)使用指针作为函数的参数虽然也能达到与使用引用的效果,但是,在被调函数中同样要给形参分配存储单元,且需要重复使用"*指针变量名"的形式进行运算,这很容易产生错误且程序的阅读性较差;

另一方面,在主调函数的调用点处,必须用变量的地址作为实参。而引用更容易使用,更清晰。

如果既要利用引用提高程序的效率,又要保护传递给函数的数据不在函数中被改变,就应使用常引用。

5.3 引用作为函数的返回值

(1)以引用返回函数值,定义函数时需要在函数名前加&

(2)用引用返回一个函数值的最大好处是,在内存中不产生被返回值的副本。

引用作为返回值,必须遵守以下规则:

1.不能返回局部变量的引用。

主要原因是局部变量会在函数返回后被销毁,因此被返回的引用就成为了"无所指"的引用,程序会进入未知状态。

2.不能返回函数内部new分配的内存的引用。

例如,被函数返回的引用只是作为一个临时变量出现,而没有被赋予一个实际的变量,那么这个引用所指向的空间(由new分配)就无法释放,造成memory leak。

3.可以返回类成员的引用,但最好是const。

这条原则可以参照Effective C++[1]的Item 30。主要原因是当对象的属性是与某种业务规则(business rule)相关联的时候,其赋值常常与某些其它属性或者对象的状态有关,因此有必要将赋值操作封装在一个业务规则当中。如果其它对象可以获得该属性的非常量引用(或指针),那么对该属性的单纯赋值就会破坏业务规则的完整性。

4.引用与一些操作符的重载

流操作符<<和>>,这两个操作符常常希望被连续使用,例如:cout << “hello” << endl; 因此这两个操作符的返回值应该是一个仍然支持这两个操作符的流引用。


http://www.ppmy.cn/news/754227.html

相关文章

PHP生成一寸照片代码,ps做一寸证件照的步骤

生活中我们经常会遇到需要证件照的场合&#xff0c;好看的证件照也能给个人形象加分。那么怎么用ps做一寸证件照呢&#xff1f;下面为大家分享用ps做一寸证件照的步骤。 我们先放一张表格&#xff0c;来了解下一般证件照所需要的尺寸&#xff1a; ps做一寸证件照的步骤&#xf…

PyQt---------信号与槽函数的关系

1.信号&#xff08;Signal&#xff09; 信号是在特定情况下被发射的一种通告。举例&#xff1a; PushButton 的信号是鼠标单击时发射的 clicked 信号 2.槽&#xff08;Slot&#xff09; 对信号相应的函数。举例&#xff1a; QWidget 有一个槽函数&#xff0c;功能是关闭窗口 …

寸照尺寸

[常识]一寸照片是多大? 一寸2.5*3.5cm295*413像素 1寸照片 平时都用寸来表示照片的规格但很多朋友包括我在内都还搞不清楚这1 寸照片到底是多大二寸照片为何不是一寸照片的两倍大一寸是多少像素等问 题现在就把常用的照片尺寸、对应的大小厘米及数码相机分…

开源项目推荐 【SkyEyeSystem】

大家好&#xff0c;今天向大家推荐一个开源项目——SkyEyeSystem。 这是一个基于Spring Boot的全网热点爬虫项目&#xff0c;旨在提供全面而准确的全网热搜数据。 关于项目 SkyEyeSystem通过定时任务间隔10min爬取全网热搜数据。目前包括的平台有&#xff1a; 微博热搜B站热…

【Redis】缓存穿透、缓存击穿、缓存雪崩的原因及解决方案

文章目录 一、缓存穿透1.1 产生原因1.2 解决方法接口校验对空值进行缓存使用布隆过滤器实时监控 二、缓存雪崩2.2 解决方法将失效时间分散开给业务添加多级缓存构建缓存高可用集群使用锁或者队列的方式设置缓存标记 三、缓存击穿3.2 解决方法使用互斥锁”提前“使用互斥锁 / 逻…

电商扣减库存_电商后台产品经理宝典

作者:清水红牙搬运 by A小蚊子丨ID:xiaowenzileyuan想了解更多,欢迎关注公众号“A小蚊子(xiaowenzileyuan)”,更多精彩内容、知识大礼包等你发现。欢迎将此文分享给更多朋友,大家共同精进电商架构 电商架构(图电商核心模块(图商品中心 管理SKU:最小库存单位管理SPU:…

Kotlin之类型系统

Kotlin之类型系统 可空类型 在任何类型后加“?”表示该变量可为空。val a: Int? null。 安全的调用 使用“?.”进行安全调用。实现方式&#xff1a;仍旧使用if判空。student?.name。 合并运算符 使用“?:”运算符。 val result a ?: 1 非空断言 使用“!!”操作…

是德频谱仪N9020A维修报错维修-安泰维修

近期&#xff0c;有客户送来一台是德N9020A频谱仪&#xff0c;故障表现为报错。工程师接到仪器后&#xff0c;对其进行故障检测。 经过工程师检查后&#xff0c;开机发现自检失败&#xff0c;报错LO Unlock&#xff0c;无基线。 经检测&#xff0c;仪器前端板损坏&#xff0c;造…