6.1 指向独立对象的引用类型

参考C++ Primer (3rd)的3.6章节

通过引用我们可以间接地操纵对象,使用方式类似于指针。但是不需要指针的语法。

引用类型由类型标识符和一个取地址操作符来定义。

1. 引用必须被初始化,不允许空引用。

int &refVal = ival;

int &refVal2;

// 错误引用必须被初始化为指向一个对象

2. 引用一旦初始化,就不能再引用其它数据。

3. 引用和被引用的变量实际上代表同一个内存的数据。

引用的所有操作都被应用在它所指的对象身上,包括取地址操作符。

本屌做过如下测试:

int ival = 111;

int *pi1 = &ival;

int &ri1 = ival;

int * const &pr1 = &ival;

cout << "int *pi1 =&ival--pi1:" << pi1 <<"--*pi1:" << *pi1 <<"--&pi1:" << &pi1<< endl;

cout << "int &ri1 = ival--ri1:"<< ri1 <<"--*ri1:(error)" << "--&ri1:" << &ri1 << endl;

cout <<"int * const &pr1 = &ival--pr1:" << pr1 <<"--*pr1:" << *pr1<< "--&pr1:" << &pr1 << endl << endl;

输出结果:

int*pi1 = &ival--pi1:0x28fee8--*pi1:111--&pi1:0x28fee4

int&ri1 = ival--ri1:111--*ri1:(error)--&ri1:0x28fee8

int *const &pr1 = &ival--pr1:0x28fee8--*pr1:111--&pr1:0x28feec

ri1是ival的引用,ri就相当于ival。对ri的所有操作都被应用在ival身上。如上:ri1指的是ival的值;&ri1指的是ival的地址。

pi1是ival的地址,*pi1指的是ival的值,&pi1指的是ival的地址的地址。

pr1引用的是指向整型变量的指针变量。也就是说pri是一个指向整型的指针变量,如果要对pri赋值的话只能赋整型变量的指针/地址。

顺便说一下:

int *pi1,int* pi1, int * pi1是等价的。也就是说“*”靠谁近或者之间有没有空格,并不影响功能。但是推荐使用int *pi1,因为考虑到一连串定义几个变量时可能出错。比如:int *pi1, *pi2, *pi3;而不是 int*pi1, pi2, pi3。

同理,“&”也是一样的。

int &ri1,int& ri1,int &ri1是等价的。也就是说“*”靠谁近或者之间有没有空格,并不影响功能。但是推荐使用int &ri1,因为考虑到一连串定义几个变量时可能出错。比如:int &ri1, &ri2, &ri3;而不是 int& ri1, ri2, ri3。

6.2 被用作函数的形式参数的引用类型

参考C++ Primer(3rd)的7.3.1章节

把参数声明成引用,实际上改变了缺省的按值传递参数的传递机制。在按值传递时,函

数操纵的是实参的本地拷贝。当参数是引用时,函数接收的是实参的左值而不是值的拷贝。

通常,传递的是形参的值或者地址的值。此时需要将形参的值拷贝(赋值)给实参,然后操纵实参。

当把参数声明为引用时,传递的是形参本身。此时不需要将形参的值拷贝(赋值)给实参,可以直接操纵形参。和指针类似。

比如:

inline vec3&vec3::operator+=(const vec3 &v)

{

e[0]+= v.e[0];

e[1] += v.e[1];

e[2] += v.e[2];

return *this;

}

形参v是一个vec3类型对象的引用,所以函数体内可以直接操作v对象(的成员变量/函数)

6.3 被用作函数返回的引用类型

c++函数的返回分为以下几种情况:

1)主函数main的返回值:这里提及一点,返回0表示程序运行成功。

2)返回非引用类型:函数的返回值用于初始化在跳用函数出创建的临时对象。用函数返回值初始化临时对象与用实参初始化形参的方法是一样 的。如果返回类型不是引用,在调用函数的地方会将函数返回值复制给临时对象。且其返回值既可以是局部对象,也可以是求解表达式的结果。

3)返回引用:当函数返回引用类型时,没有复制返回值。相反,返回的是对象本身。

例如:

inline vec3& vec3::operator+=(const vec3 &v)

{

e[0] += v.e[0];

e[1] += v.e[1];

e[2] += v.e[2];

return *this;

}

测试代码如下:

vec3 v1(1.0, 2.0,3.0);

vec3 v2(4.0, 5.0,6.0);

vec3 vt;

std::cout <<"v1: " << v1.e[0] << " " << v1.e[1]<< " " << v1.e[2] << endl;

std::cout <<"v2: " << v2.e[0] << " " << v2.e[1]<< " " << v2.e[2] << endl;

vt = v1.operator+=(v2);

std::cout <<"v1====================: " << v1.e[0] << " "<< v1.e[1] << " " << v1.e[2] << endl;

std::cout <<"vt = v1.operator+=(v2): " << vt.e[0] << " "<< vt.e[1] << " " << vt.e[2] << endl;

测试结果如下:

v1: 1 2 3

v2: 4 5 6

v1====================:5 7 9

vt =v1.operator+=(v2): 5 7 9

根据函数体,operator+=()返回的调用该函数的对象的引用,此处为v1的引用。所以,将v1的应用赋值给vt就相当于将v1赋值给vt。

根据测试结果,v1,vt两个向量确实相等。

又感觉引用和指针好像哈!这样说吧,引用能干的事情,指针都能干。那么问题来了,为什么还要“引用”这东西???

网友给出一个非常好的解释:(够用,简单,可靠)

答案是“用适当的工具做恰如其分的工作”。

指针能够毫无约束地操作内存中的如何东西,尽管指针功能强大,但是非常危险。

就象一把刀,它可以用来砍树、裁纸、修指甲、理发等等,谁敢这样用?

如果的确只需要借用一下某个对象的“别名”,那么就用“引用”,而不要用“指针”,以免发生意外。比如说,某人需要一份证明,本来在文件上盖上公章的印子就行了,如果把取公章的钥匙交给他,那么他就获得了不该有的权利。

http://blog.csdn.net/thisispan/article/details/7456169

问题六:C++中是干嘛用的(引用类型)相关推荐

  1. bootstraptable设置行高度_条码打印软件中不干胶卷纸的标签设置方法

    条码打印软件中的标签设置是根据打印机中的实际标签纸的情况进行设置的,不同的标签纸有不同的设置方法(如A4的平张纸,或者单排.双排.多排的不干胶卷纸都有相对的设置方法).今天就用中琅条码打印软件给大家演 ...

  2. (六) carla中导入AdditionalMaps

    (六) carla中导入AdditionalMaps 前言 carlacarlacarla 中可以通过 world = client.get_world() 来直接让客户端使用当前服务端默认的 wor ...

  3. [矩阵的三角分解系列六] Eigen中的三角分解

    Eigen中的三角分解 简介 安装命令 三角分解函数 使用范例 矩阵的三角分解是求解线性方程组常用的方法,包括LU分解,LDU分解,杜利特(Doolittle)分解,克劳特(Crout)分解,LLT( ...

  4. 全网惟一面向软件测试人员的Python基础教程-在Python中怎么干倒字符串?

    全网惟一面向软件测试人员的Python基础教程 起点:<python软件测试实战宝典>介绍 第一章 为什么软件测试人员要学习Python 第二章 学Python之前要搞懂的道理 第三章 你 ...

  5. 优思学院:六西格玛中的水平对比方法是什么?

    水平对比,就是比较不同事物之间的差异. 这个概念在六西格玛管理中也很重要,也就是我们经常说的标杆管理,经常被用来寻找行业中最好的做法,以帮助组织改进自身的绩效. 在六西格玛管理中,水平对比有三种常见的 ...

  6. 优思学院|六西格玛中的线性回归分析有什么意义?

    回归分析可用于寻找(A)变量之间的关系,(B)预测结果或决策信息(C)通过实验或纵向研究寻找变量之间的因果关系. 以上(A)可以说是必然的,但(B)和(C)则要视乎研究的目标和变量是什么,因为有关系( ...

  7. 高等数学同济六版中函数运算一节例题的分析

    在高等数学同济第六版教材中,函数运算一节,有一道例题,引起了我及很多人的困扰,原题如下: 该题目教材中的原解如下: 实际上,教材已经说得很清楚了,只不过我们由于思维惯性,误解了教材内容,具体分析如下: ...

  8. 优思学院|六西格玛中的非正态的数据如何处理?教你这一招

    正态分佈的假设 正态分布的假设,经常应用于很多统计分析方法中,例如控制图(Control Chart). 制程能力分析(Cp/Cpk).t-检验.及变异数分析 (Analysis of varianc ...

  9. JDBC编程六步中遇到的问题

    首先,我们介绍一下 JDBC 编程六步 (参考 pink老师) 一. 导入驱动 jar包 导入驱动jar包的两种方式 //方式1 1. 在任务栏创建文件夹(Directory)libs--复制(D:\ ...

最新文章

  1. ASN.1简介及OpenSSL中ASN.1接口使用举例
  2. 相似度矩阵遍历 python
  3. java用jdbc来rollback,jdbc rollback,该怎么解决
  4. MATLAB控制运算精度
  5. Dubbo注册中心宕机
  6. 通过C#/.NET API使用CNTK
  7. ec20驱动_物联网基础:移远EC20固件升级
  8. python安卓版开发环境搭建_React Native Android 开发环境搭建(Windows 版)
  9. php读这文件速度,php 测试硬盘读写-php 测试硬盘写速率
  10. Spring Boot中自动配置原理以及日志的基本使用
  11. 单链表实现反转的三种方法
  12. 计算机网络---HTTP状态码
  13. 2015年主流的页面导航菜单设计
  14. PaddlePaddle(2)——数据获取与处理(以CV任务为主)
  15. 【原创】在Windows 环境下利用SVN和Apache以及Ankh配置源代码管理服务
  16. (转)中国著名黑客你知道多少?
  17. 终极算法:机器学习和人工智能如何重塑世界笔记
  18. 22轴三菱Q系列程序案例点胶机,QJ71C24串口与位移传感器通信案例
  19. iOS xcode中生成和打包ipa文件的方法和步骤
  20. 智能营销模型-Uplift Model详解及Python使用

热门文章

  1. Xcode 插件失效的临时解决方案
  2. Postfix+Mysql+Apache+Dovecot+Thunderbird+Extmail+E
  3. [转]实现双网卡局域网和广域网同时上网
  4. Exception in thread main java.lang.NoClassDef...
  5. 关于sinX与y的大小比较取值范围计算
  6. python爬虫基础17-抓包工具使用
  7. Spark2.2(三十九):如何根据appName监控spark任务,当任务不存在则启动(任务存在当超过多久没有活动状态则kill,等待下次启动)...
  8. PhpSpreadsheet如何读取excel文件
  9. sqlserver 迁移
  10. 使用spark-shell从本地读取文件不成功的的操作。