C++/C++11中引用的使用
引用(reference)是一种复合类型(compound type)。引用为对象起了另外一个名字,引用类型引用(refer to)另外一种类型。通过将声明符写成&d的形式来定义引用类型,其中d是声明的变量名。
一、一般引用:
一般在初始化变量时,初始值会被拷贝到新建的对象中。然而定义引用时,程序把引用和它的初始值绑定(bind)在一起,而不是将初始值拷贝给引用。一旦初始化完成,引用将和它的初始值对象一直绑定在一起。因为无法令引用重写绑定到另外一个对象,因此引用必须初始化。
为引用赋值,实际上是把值赋给了与引用绑定的对象。获取引用的值,实际上是获取了与引用绑定的对象的值。同理,以引用作为初始值,实际上是以与引用绑定的对象作为初始值。
引用并非对象,相反的,它只是为一个已经存在的对象所起的另外一个名字,引用即别名。定义了一个引用之后,对其进行的所有操作都是在与之绑定的对象上进行的。
因为引用本身不是一个对象,所以不能定义引用的引用。
允许在一条语句中定义多个引用,其中每个引用标识符都必须以符号&开头。
引用只能绑定到对象上,而不能与字面值或某个表达式的计算结果绑定在一起。
二、const的引用:
可以把引用绑定到const对象上,就像绑定到其它对象上一样,称之为对常量的引用(reference to const)。与普通引用不同的是,对常量的引用不能被用作修改它所绑定的对象。
常量的引用仅对引用可参与的操作做出了限定,对于引用的对象本身是不是一个常量未作限定。因为对象也可能是个非常量,所以允许通过其它途径改变它的值。
三、传引用参数:
通过使用引用形参,允许函数改变一个或多个实参的值。
使用引用避免拷贝:拷贝大的类类型对象或者容器对象比较低效,甚至有的类类型(包括IO类型在内)根本就不支持拷贝操作。当某种类型不支持拷贝操作时,函数只能通过引用形参访问该类型的对象。
使用引用形参返回额外信息:一个函数只能返回一个值,然而有时函数需要同时返回多个值,引用形参为一次返回多个结果提供了有效的途径。
函数参数是否需要传引用的判别:(1)、需要在函数内部改变实参的值;(2)、函数传入值较大,为避免拷贝的代价,使用引用。
在函数调用时在内存中不会生成副本,用引用传递函数的参数,能保证参数传递中不产生副本,提高传递的效率,且通过const的使用,保证了引用传递的安全性。
Advantages of passing by reference:
(1)、It allows a function to change the value of the argument, which is sometimes useful.Otherwise, const references can be used to guarantee the function won’t change the argument.
(2)、Because a copy of the argument is not made, it is fast, even when used with large structs or classes.
(3)、References can be used to return multiple values from a function.
(4)、References must be initialized, so there’s no worry about null values.
Disadvantages of passing by reference:
(1)、Because a non-const reference cannot be made to an rvalue (e.g. a literal or an expression), reference arguments must be normal variables.
(2)、It can be hard to tell whether a parameter passed by non-const reference is meant to be input, output, or both. Judicious use of const and a naming suffix for out variables can help.
(3)、It’s impossible to tell from the function call whether the argument may change. An argument passed by value and passed by reference looks the same. We can only tell whether an argument is passed by value or reference by looking at the function declaration. This can lead to situations where the programmer does not realize a function will change the value of the argument.
When to use pass by reference:
(1)、When passing structs or classes (use const if read-only).
(2)、When you need the function to modify an argument.
When not to use pass by reference:
(1)、When passing fundamental types (use pass by value).
四、右值引用:
为了支持移动操作,C++11引入了一种新的引用类型----右值引用(rvalue reference)。所谓右值引用就是必须绑定到右值的引用。通过&&而不是&来获得右值引用。右值引用有一个重要的性质----只能绑定到一个将要销毁的对象。因此,可以自由地将一个右值引用的资源”移动”到另一个对象中。
一般而言,一个左值表达式表示的是一个对象的身份,而一个右值表达式表示的是对象的值。
类似任何引用,一个右值引用也不过是某个对象的另一个名字而已。对于常规引用(为了与右值引用区分开来,可以称之为左值引用(lvalue reference)),不能将其绑定到要求转换的表达式、字面常量或是返回右值的表达式。右值引用有着完全相反的绑定特性:可以将一个右值引用绑定到这类表达式上,但不能将一个右值引用直接绑定到一个左值上。
返回左值引用的函数,连同赋值、下标、解引用和前置递增/递减运算符,都是返回左值得表达式的例子。可以将一个左值引用绑定到这类表达式的结果上。
返回非引用类型的函数,连同算术、关系、位以及后置递增/递减运算符,都生成右值。不能将一个左值引用绑定到这类表达式上,但可以将一个const的左值引用或者一个右值引用绑定到这类表达式上。
左值持久,右值短暂:左值有持久的状态,而右值要么是字面常量,要么是在表达式求值过程中创建的临时对象。
由于右值引用只能绑定到临时对象,可知:所引用的对象将要被销毁;该对象没有其它用户。这两个特性意味着,使用右值引用的代码可以自由地接管所引用的对象的资源。
变量是左值:变量可以看作只有一个运算对象而没有运算符的表达式。
变量是左值,因此不能将一个右值引用直接绑定到一个变量上,即使这个变量是右值引用类型也不行。
虽然不能就将一个右值引用直接绑定到一个左值上,但可以显示地将一个左值转换为对应的右值引用类型。还可以通过调用一个名为move的新标准库函数来获得绑定到左值上的右值引用,此函数定义在头文件utility中。move调用告诉编译器:有一个左值,但希望像一个右值一样处理它。在调用move之后,我们不能对移后源对象的值做任何假设。
我们可以销毁一个移后源对象,也可以赋予它新值,但不能使用一个移后源对象的值。
关于C++11中右值引用的更多介绍可以参数:http://blog.csdn.net/fengbingchun/article/details/52562004
五、引用作为函数返回值
以引用返回函数值,定义函数时需要在函数名前加&。用引用返回一个函数值得最大好处是,在内存中不产生被返回值的副本。
引用作为返回值,必须遵守以下规则:
(1)、不能返回局部变量的引用。
(2)、不能返回函数内部new分配的内存的引用。
(3)、可以返回类成员的引用,但最好是const。
当函数返回值类型为引用时,一般就用引用类型去接收,如果用非引用类型接收,就等于将函数返回的引用的数据值,复制给了该接收对象,和函数返回非引用类型是一样的效果。
不可以将常引用当作函数返回值返回。
能用常引用的地方尽量用常引用。
以下是测试代码:
#include "reference.hpp"
#include <iostream>
#include <utility> // std::moveint test_reference_1()
{// 1. 普通的引用int ival = 1024;int &refVal = ival; // refVal指向ival(是ival的另一个名字)//int &refVal2; // error:引用必须被初始化int &refVal3 = refVal; // refVal3绑定到了那个与refVal绑定的对象上,这里就是绑定到ival上// 利用与refVal绑定的对象的值初始化变量iint i = refVal; // correct:i被初始化为ival的值// 允许在一条语句中定义多个引用,其中每个引用标识符都必须以符号&开头int i1 = 1024, i2 = 2048;int &r = i1, r2 = i2;int i3 = 1024, &ri = i3;int &r3 = i3, &r4 = i2; // r3和r4都是引用//int &refVal4 = 10; // error: 引用类型的初始值必须是一个对象double dval = 3.14;//int &refVal5 = dval; // error: 此处引用类型的初始值必须是int型对象const int &refVal6 = dval; // correct// 编译器把上述语句变成了如下形式://const int temp = dval; // 由双精度浮点数生成一个临时的整型常量//const int &refVal6 = temp; // 让refVal6绑定这个临时量// 2. const的引用// 对常量的引用不能被用作修改它所绑定的对象const int ci = 1024;const int &r1 = ci; // correct: 引用及其对应的对象都是常量//r1 = 42; // error: r1是对常量的引用//int &r2 = ci; // error: 试图让一个非常量引用指向一个常量对象int i4 = 42;const int &r6 = i4; // 允许将const int&绑定到一个普通int对象上const int &r7 = 42; // correct: r7是一个常量引用const int &r8 = r6 * 2; // correct: r8是一个常量引用//int &r9 = r6 * 2; // error: r9是一个普通的非常量引用// 常量的引用仅对引用可参与的操作做出了限定,对于引用的对象本身是不是一个常量未作限定int x = 42;int &rx = x; // 引用rx绑定对象xconst int &ry = x; // ry也绑定对象x,但是不允许通过ry修改x的值rx = 0; // rx并非常量,x的值修改为0//ry = 0; // error: ry是一个常量引用return 0;
}// 该函数接受一个int对象的引用,然后将对象的值置为0
static void reset(int &i) // i是传给reset函数的对象的另一个名字
{i = 0; // 改变了i所引用对象的值
}int test_reference_2()
{int j = 42;reset(j); // j采用引用方式,它的值被改变fprintf(stderr, "j = %d\n", j); // j = 0return 0;
}int test_reference_3()
{int i = 42;int &r = i; // correct: r引用i//int &&rr = i; // error: 不能将一个右值引用绑定到一个左值上//int &r2 = i * 42; // error: i*42是一个右值const int &r3 = i * 42; // correct: 可以将一个const的引用绑定到一个右值上int &&rr2 = i * 42; // correct: 将rr2绑定到乘法结果上int &&rr1 = 42; // correct: 字面常量是右值//int &&rr3 = rr1; // error: 表达式rr1是左值int &&rr4 = std::move(rr1); // correctreturn 0;
}
GitHub: https://github.com/fengbingchun/Messy_Test
相关文章:

node.js学习5--------------------- 返回html内容给浏览器
/*** http服务器的搭建,相当于php中的Apache或者java中的tomcat服务器*/ // 导包 const httprequire("http"); const fsrequire("fs"); //创建服务器 /*** 参数是一个回调函数,回调函数2个参数,1个是请求参数,一个是返回参数*/ let serverhttp.createServe…

内核分析阅读笔记
内核分析阅读笔记 include/Linux/stddef.h中macro offsetof define,list: #define offsetof(TYPE,MEMBER) ((size_t) &((TYPE *)0)->MEMBER) offsetof macro对于上述示例的展开剂分析:&((struct example_struct *)0)->list表示当结构example_struct正好在地址0上…

杨强教授力荐,快速部署落地深度学习应用的实践手册
香港科技大学计算机科学与工程学系讲座教授、国际人工智能联合会(IJCAI)理事会主席(2017—2019)、深圳前海微众银行首席AI 官 杨强为《深度学习模型及应用详解》一书撰序,他提到现在亟需一本介绍深度学习技术实践的图书…
OpenFace库(Tadas Baltrusaitis)中基于HOG进行正脸人脸检测的测试代码
Tadas Baltrusaitis的OpenFace是一个开源的面部行为分析工具,它的源码可以从https://github.com/TadasBaltrusaitis/OpenFace下载。OpenFace主要包括面部关键点检测(facial landmard detection)、头部姿势估计(head pose estimation)、面部动作单元识别(facial acti…

nginx conf 文件配置
打印输出: location / { default_type text/plain; return 502 "$uri"; } $remode_addr 获取访问者的ID$request_method 判断提交方式 GET POST$http_user_agent 获取浏览器软件 if (条件) {} #if之后要有空格 条件3种写法: 1: 来判断相等,用于字符串比较 …

js中 字符串与Unicode 字符值序列的相互转换
一. 字符串转Unicode 字符值序列 var str "abcdef"; var codeArr []; for(var i0;i<str.length;i){codeArr.push(str.charCodeAt(i)); } console.log(codeArr);-->[97, 98, 99, 100, 101, 102] 二.Unicode 字符值序列转字符串 var str String.fromCharCode…
OpenFace库(Tadas Baltrusaitis)中基于Haar Cascade Classifiers进行人脸检测的测试代码
Tadas Baltrusaitis的OpenFace是一个开源的面部行为分析工具,它的源码可以从 https://github.com/TadasBaltrusaitis/OpenFace 下载。OpenFace主要包括面部关键点检测(facial landmard detection)、头部姿势估计(head pose estimation)、面部动作单元识别(facial a…

Uber提出损失变化分配方法LCA,揭秘神经网络“黑盒”
作者 | Janice Lan,Rosanne Liu等译者 | 清儿爸责编 | 夕颜出品 | AI科技大本营(ID: rgznai100)【导读】神经网络(Neural networks,NN)在过去十年来硕果累累,推动了整个行业的机器学习进程。然而࿰…

范登读书解读《亲密关系》(婚姻、爱情) 笔记
来源:邀请你看《樊登解读《亲密关系》(已婚人士必看)》,https://url.cn/5HJvLk5?sfuri 人们在童年的时候始终追寻着两种东西,第一种叫做归属感,第二叫做确认自己的重要性、价值感。 如果再童年的时候缺失这…

myeclipse莫名其妙的问题
2019独角兽企业重金招聘Python工程师标准>>> 怎么刷新,clean项目都不管用,结果删除相应工作空间下的那个项目就行。类似路径如D:\workspace\.metadata\.plugins\org.eclipse.core.resources\.projects 转载于:https://my.oschina.net/u/14488…

数据科学家需要知道的5种图算法
作者:Rahul Agarwal编译:ronghuaiyang来源 | AI公园(ID:AI_Paradise)【导读】因为图分析是数据科学家的未来。作为数据科学家,我们对pandas、SQL或任何其他关系数据库非常熟悉。我们习惯于将用户的属性以列的形式显示在…
在Windows7/10上快速搭建深度学习框架Caffe开发环境
之前在 http://blog.csdn.net/fengbingchun/article/details/50987353 中介绍过在Windows7上搭建Caffe开发环境的操作步骤,那时caffe的项目是和其它依赖项目分开的,每次换新的PC机时再次重新配置搭建还是很不方便,而且caffe的版本较老&#x…

扫码下单支持同桌单人点餐FAQ
一、使用场景 满足较多商户希望同一桌台,各自点各自的菜品的业态场景(例如杭味面馆,黄焖鸡米饭店,面馆等大多数轻快餐店) 二、配置步骤及注意事项 管理员后台配置--配置管理--店铺配置--扫码点餐tab页 1、开启扫码下单…

使用photoshop 10.0制作符合社保要求的照片
2019独角兽企业重金招聘Python工程师标准>>> 北京市社保新参统人员照片修制方法 修改目标:照片规格:358像素(宽)×441像素(高),分辨率350dpi。 颜色模式:24位RGB真彩色。 储存格式&am…

C++11中std::addressof的使用
C11中的std::addressof获得一个对象的实际地址,即使 operator& 操作符已被重载。它常用于原本要使用 operator& 的地方,它接受一个参数,该参数为要获得地址的那个对象的引用。一般,若operator &()也被重载且不一致的话…

一份职位信息的精准推荐之旅,从AI底层架构说起
整理 | 夕颜出品 | AI科技大本营(ID:rgznai100)【导读】也许,每天早上你的邮箱中又多了一封职位推荐信息,点开一看,你可能发现这些推荐正合你意,于是按照这些信息,你顺利找到一份符合自己期待的…

Vue.js 生命周期
2019独角兽企业重金招聘Python工程师标准>>> 每个 Vue 实例在被创建之前都要经过一系列的初始化过程 vue在生命周期中有这些状态, beforeCreate,created,beforeMount,mounted,beforeUpdate,updated,beforeDestroy,destroyed。Vue在实例化的过程中&#x…

AX2009取销售订单的税额
直接用以下方法即可: Tax::calcTaxAmount(salesLine.TaxGroup, salesLine.TaxItemGroup, systemDateGet(), salesLine.CurrencyCode, salesParmLine.LineAmount, salesTable.taxModuleType()); salesParmLine.LineAmount:这个直接取的是装箱单或者发票…

Dubbo源码解析之服务路由策略
1. 简介 服务目录在刷新 Invoker 列表的过程中,会通过 Router 进行服务路由,筛选出符合路由规则的服务提供者。在详细分析服务路由的源码之前,先来介绍一下服务路由是什么。服务路由包含一条路由规则,路由规则决定了服务消费者的调…

C++中std::reverse和std::reverse_copy的使用
std::reverse:反转排序容器内指定范围中的元素。std::reverse_copy与std::reverse唯一的区别是:reverse_copy会将结果拷贝到另外一个容器中,而不影响原容器的内容。std::reverse: defined in header <algorithm>, reverses the order …

真相!30K拿到互联网大厂offer,网友:我服了!
最近笔者在知乎刷到一个帖子,其中,这条回答让人印象深刻:其实,最近几年人工智能大火,其中深度学习岗位的薪酬爆增,BAT大厂高薪招聘AI人才,收到的简历却寥寥无几?究竟是大厂岗位要求高…

OracleDesigner学习笔记1――安装篇
OracleDesigner学习笔记1――安装篇 QQ:King MSN:qiutianwhmsn.com Email:qqkinggmail.com 一. 前言 Oracle是当今最流行的关系型数据库之一,和很多朋友一样,我也是一个Oracle的爱好者,从…

C++/C++11中std::queue的使用
std::queue: 模板类queue定义在<queue>头文件中。队列(Queue)是一个容器适配器(Container adaptor)类型,被特别设计用来运行于FIFO(First-in first-out)场景,在该场景中,只能从容器一端添加(Insert)元素,而在另一端提取(Ext…

常见的http状态码(Http Status Code)
常见的http状态码:(收藏学习) 2**开头 (请求成功)表示成功处理了请求的状态代码。 200 (成功) 服务器已成功处理了请求。 通常,这表示服务器提供了请求的网页。201 (已创…

“不给钱就删库”的勒索病毒, 程序员该如何防护?
作者 | 阿木,王洪鹏,运营有个人公众号新新生活志。目前任职网易云计算技术部高级工程师,近3年云计算从业经验,爱读书、爱写作、爱技术。责编 | 郭芮来源 | CSDN(ID:CSDNnews)近期一家名为ProPub…

ruby实时查看日志
(文章是从我的个人主页上粘贴过来的, 大家也可以访问我的主页 www.iwangzheng.com) 在调试代码的时候,把日志文件打开,边操作边调试能很快帮助我们发现系统中存在的问题。 $tail rails_2014_03_03.log -f转载于:https://www.cnblogs.com/iw…

干货 | OpenCV看这篇就够了,9段代码详解图像变换基本操作
作者 | 王天庆,长期从事分布式系统、数据科学与工程、人工智能等方面的研究与开发,在人脸识别方面有丰富的实践经验。现就职某世界100强企业的数据实验室,从事数据科学相关技术领域的预研工作。来源 | 大数据(ID:hzdas…

C++/C++11中std::priority_queue的使用
std::priority_queue:在优先队列中,优先级高的元素先出队列,并非按照先进先出的要求,类似一个堆(heap)。其模板声明带有三个参数,priority_queue<Type, Container, Functional>, 其中Type为数据类型,Container为…

left join 和 left outer join 的区别
老是混淆,做个笔记,转自:https://www.cnblogs.com/xieqian111/p/5735977.html left join 和 left outer join 的区别 通俗的讲: A left join B 的连接的记录数与A表的记录数同 A right join B 的连接的记录数与…

php减少损耗的方法之一 缓存对象
即把实例后的对象缓存起来(存入变量),当需要再次实例化时,先去缓存里查看是否存在。存在则返回。否则实例化。转载于:https://www.cnblogs.com/zuoxiaobing/p/3581139.html