引用,顾名思义是某一个变量或对象的别名,对引用的操作与对其所绑定的变量或对象的操作完全等价

语法:类型 &引用名=目标变量名;

特别注意:

1.&不是求地址运算符,而是起标志作用

2.引用的类型必须和其所绑定的变量的类型相同

#include<iostream>
using namespace std;
 int main(){
     double a=10.3;
     int &b=a; //错误,引用的类型必须和其所绑定的变量的类型相同
     cout<<b<<endl;
 }

3.声明引用的同时必须对其初始化,否则系统会报错

4、引用相当于变量或对象的别名,因此不能再将已有的引用名作为其他变量或对象的名字或别名

5.引用不是定义一个新的变量或对象,因此内存不会为引用开辟新的空间存储这个引用

6.对数组的引用

语法:类型 (&引用名)[数组中元素数量]=数组名;
#include<iostream>
using namespace std;
int main(){
    ]={,,};
    ]=a;//对数组的引用
    cout<<&a[]<<]<<endl;
    cout<<&a[]<<]<<endl;
    cout<<&a[]<<]<<endl;
    ;
}

7.对指针的引用

语法:类型 *&引用名=指针名;//可以理解为:(类型*) &引用名=指针名,即将指针的类型当成类型*
#include<iostream>
using namespace std;
int main(){
    ;
    int *ptr=&a;
    int *&new_ptr=ptr;
    cout<<&ptr<<" "<<&new_ptr<<endl;
    ;
}

二、引用的应用

A.引用作为函数的参数
#include<iostream>
using namespace std;
void swap(int &a,int &b){//引用作为函数的参数
    int temp=a;
    a=b;
    b=temp;
}
int main(){
    ,value2=;
    cout<<"----------------------交换前----------------------------"<<endl;
    cout<<"value1的值为:"<<value1<<endl;
    cout<<"value2的值为:"<<value2<<endl;
    swap(value1,value2);
    cout<<"----------------------交换后----------------------------"<<endl;
    cout<<"value1的值为:"<<value1<<endl;
    cout<<"value2的值为:"<<value2<<endl;
    ;
}

特别注意:

1.当用引用作为函数的参数时,其效果和用指针作为函数参数的效果相当。当调用函数时,函数中的形参就会被当成实参变量或对象的一个别名来使用,也就是说此时函数中对形参的各种操作实际上是对实参本身进行操作,而非简单的将实参变量或对象的值拷贝给形参

2.通常函数调用时,系统采用值传递的方式将实参变量的值传递给函数的形参变量。此时,系统会在内存中开辟空间用来存储形参变量,并将实参变量的值拷贝给形参变量,也就是说形参变量只是实参变量的副本而已;并且如果函数传递的是类的对象,系统还会调用类中的拷贝构造函数来构造形参对象。而使用引用作为函数的形参时,由于此时形参只是要传递给函数的实参变量或对象的别名而非副本,故系统不会耗费时间来在内存中开辟空间来存储形参。因此如果参数传递的数据较大时,建议使用引用作为函数的形参,这样会提高函数的时间效率,并节省内存空间

3.使用指针作为函数的形参虽然达到的效果和使用引用一样,但当调用函数时仍需要为形参指针变量在内存中分配空间,而引用则不需要这样,故在C++中推荐使用引用而非指针作为函数的参数

4.如果在编程过程中既希望通过让引用作为函数的参数来提高函数的编程效率,又希望保护传递的参数使其在函数中不被改变,则此时应当使用对常量的引用作为函数的参数。

5.数组的引用作为函数的参数:C++的数组类型是带有长度信息的,引用传递时如果指明的是数组则必须指定数组的长度

B.常引用

语法:const 类型 &引用名=目标变量名;

常引用不允许通过该引用对其所绑定的变量或对象进行修改

#include<iostream>
using namespace std;
int main(){
    ;
    const int &new_a=a;
    new_a=;//错误!不允许通过常引用对其所绑定的变量或对象进行修改
    ;
}
C.引用作为函数的返回值
语法:类型 &函数名(形参列表){ 函数体 }

特别注意:

1.引用作为函数的返回值时,必须在定义函数时在函数名前将&

2.用引用作函数的返回值的最大的好处是在内存中不产生返回值的副本

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

4.不能返回函数内部通过new分配的内存的引用。虽然不存在局部变量的被动销毁问题,但如果被返回的函数的引用只是作为一个临时变量出现,而没有将其赋值给一个实际的变量,那么就可能造成这个引用所指向的空间(有new分配)无法释放的情况(由于没有具体的变量名,故无法用delete手动释放该内存),从而造成内存泄漏。因此应当避免这种情况的发生

5当返回类成员的引用时,最好是const引用。这样可以避免在无意的情况下破坏该类的成员。

6.可以用函数返回的引用作为赋值表达式中的左值

D.用引用实现多态

在C++中,引用是除了指针外另一个可以产生多态效果的手段。也就是说一个基类的引用可以用来绑定其派生类的实例

class Father;//基类(父类)
class Son:public Father{.....}//Son是Father的派生类
Son son;//son是类Son的一个实例
Father &ptr=son;//用派生类的对象初始化基类对象的使用

特别注意:

ptr只能用来访问派生类对象中从基类继承下来的成员如果基类(类Father)中定义的有虚函数,那么就可以通过在派生类(类Son)中重写这个虚函数来实现类的多态。

三、总结

1.在引用的使用中,单纯给某个变量去别名是毫无意义的,引用的目的主要用于在函数参数的传递中,解决大块数据或对象的传递效率和空间不如意的问题

2.用引用传递函数的参数,能保证参数在传递的过程中不产生副本,从而提高传递效率,同时通过const的使用,还可以保证参数在传递过程中的安全性

3.引用本身是目标变量或对象的别名,对引用的操作本质上就是对目标变量或对象的操作。因此能使用引用时尽量使用引用而非指针

参考:https://www.cnblogs.com/duwenxing/p/7421100.html

相较于别人写的博客,自己写的真的是太low了,自己一定会更加努力的,不仅仅是技术,博客也要写好。能够起到交流的作用

(转载)c++引用的更多相关文章

  1. 动态时间规整(DTW) 转载

    Dynamic Time Warping(DTW)诞生有一定的历史了(日本学者Itakura提出),它出现的目的也比较单纯,是一种衡量两个长度不同的时间序列的相似度的方法.应用也比较广,主要是在模板匹 ...

  2. C# 格式化字符串(转载)

    1 前言 如果你熟悉Microsoft Foundation Classes(MFC)的CString,Windows Template Library(WTL)的CString或者Standard ...

  3. @Value取不到值的原因(引用application.properties中自定义的值)

    在spring mvc架构中,如果希望在程序中直接使用properties中定义的配置值,通常使用一下方式来获取: @Value("${tag}") private String ...

  4. 转载 .Net多线程编程—任务Task https://www.cnblogs.com/hdwgxz/p/6258014.html

    .Net多线程编程—任务Task   1 System.Threading.Tasks.Task简介 一个Task表示一个异步操作,Task的创建和执行是独立的. 只读属性: 返回值 名称 说明 ob ...

  5. <转载>Mac下,使用sshpass让iterm2支持多ssh登录信息保存

    windows里有个Xshell非常的方便好使,因为它能保存你所有的ssh登录帐号信息.MAC下并没有xshell,有些也提供这样的功能,但效果都不好.iterm2是很好的终端,但却不能很好的支持多p ...

  6. visual studio 2010 winform程序不能添加对system.web的引用

    visual studio 2010 winform程序不能添加对system.web的引用[转载] 需要引用到System.Web.发现没有“System.Web”.在通过“浏览”方式,找到该DLL ...

  7. C中有关引用和指针的异同

    参考于https://blog.csdn.net/wtzdedaima/article/details/78377201 C语言也学了蛮久的,其实一直都没有用到过或者碰到过引用的例子.前端时间再全面复 ...

  8. .Net多线程编程—并发集合

    并发集合 1 为什么使用并发集合? 原因主要有以下几点: System.Collections和System.Collections.Generic名称空间中所提供的经典列表.集合和数组都不是线程安全 ...

  9. .Net多线程编程—System.Threading.Tasks.Parallel

    System.Threading.Tasks.Parallel类提供了Parallel.Invoke,Parallel.For,Parallel.ForEach这三个静态方法. 1 Parallel. ...

随机推荐

  1. 【JavaFx教程】第一部分:Scene Builder

    第一部分的主题 开始了解 JavaFX . 创建并运行一个 JavaFX 项目. 使用 Scene Builder 来设计用户界面. 使用 模型 - 视图 - 控制器(MVC)模式 构造基础的应用. ...

  2. linux7 安装GitLab

    1.安装Linux虚拟机-- 安装后配置a.停止防火墙# systemctl stop firewalld.service# systemctl disable firewalld.service# ...

  3. contenttypes组件 (处理大量外键)

    介绍 Django contenttypes是一个非常有用的框架,主要用来创建模型间的通用关系(generic relation).   https://www.cnblogs.com/huchong ...

  4. Ubuntu14.16.18更新源

    一.源概述 源,可以认为是软件库,使用apt-get install安装的时候,会在源保存的库中进行搜索,因此源(默认源在欧洲)会影响下载速度和资源数量 二.更新源 1.步骤 编辑/etc/apt/s ...

  5. js 从URL上获取参数

    //获取匹配的        function getUrlParam(name) {             var reg = new RegExp("(^|&)" + ...

  6. 关于Web中列表页面的加载问题

    2017年5月23日,天气晴朗.尽管昨晚睡的不踏实,好在今天心情还不是很糟糕,近来事情颇多,尤其是对于TA的改变,至少目前还是没有习惯,但时间将会解决一切,这点深有体会.此时此刻,又想起了苏东坡的那首 ...

  7. webpack4.x初使用

    1.nodejs环境,建议下载v8.2以上版本的,低版本怕是有些api已经废弃,链接附上(https://npm.taobao.org/mirrors/node/) 2.网上一些教程有的是webpac ...

  8. <Android 基础(三十四)> TabLayout 从头到脚

    1. 简介 1.TabLayout给我们提供的是一排横向的标签页 2.#newTab()这个方法来创建新的标签页,然后用过#setText()和#setIcon方法分别修改标签页的文本和图标,创建完成 ...

  9. php递归获取无限分类菜单

    从数据库获取所有菜单信息,需要根据id,pid字段获取主菜单及其子菜单,以及子菜单下的子菜单,可以通过函数递归来实现. <?php class Menu { public $menu = arr ...

  10. Java学习笔记之异常处理

    一.异常的分类 1.由Java虚拟机抛出的异常(Error):程序无法处理的问题,用户不用去进行处理(虚拟机错误丶内存溢出错误丶线程死锁) 2.Exception异常:程序本身可以进行处理的异常 1. ...