(重要)使用引用的一些注意点:

1.引用不能绑定临时数据,也不能绑定任何无法获取内存地址的常量,表达式,或值,常引用除外。

第一种写法:(错误)

  1. int func_int(){
  2. int n = ;
  3. return n;
  4. }
  5.  
  6. int main(){
  7.  
  8. int m = , n = ;
  9. int &r1 = m + n;
  10. int &r2 = m + ;
  11. int &r3 = * ;
  12. int &r4 = ;
  13. int &r5 = func_int();
  14.  
  15. return ;
  16. }

第二种写法:

  1. bool isOdd(int &n){
  2. if(n/ == ){
  3. return false;
  4. }else{
  5. return true;
  6. }
  7. }
  8.  
  9. int main(){
  10. int a = ;
  11. isOdd(a); //正确
  12. isOdd(a + ); //错误
  13. isOdd(); //错误
  14. isOdd( + ); //错误
  15.  
  16. return ;
  17. }

第三种写法(正确)

  1. int func_int(){
  2. int n = ;
  3. return n;
  4. }
  5.  
  6. int main(){
  7. int m = , n = ;
  8. const int &r1 = m + n;
  9. const int &r2 = m + ;
  10. const int &r3 = * ;
  11. const int &r4 = ;
  12. const int &r5 = func_int();
  13.  
  14. return ;
  15. }

第四种写法:(正确)

  1. bool isOdd(const int &n){ //改为常引用
  2. if(n/ == ){
  3. return false;
  4. }else{
  5. return true;
  6. }
  7. }
  8.  
  9. int a = ;
  10. isOdd(a); //正确
  11. isOdd(a + ); //正确
  12. isOdd(); //正确
  13. isOdd( + ); //正确

为什么加了const就可以?这是因为将常引用绑定到临时数据时,编译器采取了一种妥协机制:编译器会为临时数据创建一个新的、无名的临时变量,并将临时数据放入该临时变量中,然后再将引用绑定到该临时变量。注意,临时变量也是变量,所有的变量都会被分配内存。

2.const修饰引用时三种写法的区别:

第一种写法(错误)

  1. int a = ;
  2. int & const r = a;

第二种写法(正确)

  1. int a = ;
  2. int const &r = a;

第三种写法(正确)

  1. int a = ;
  2. const int &r = a;

上述三种写法中,第一种写法是严重错误的。因为引用在定义时就必须初始化,并且以后也要从一而终,不能再指向其它数据,这也就意味着r本来就不能改变指向,加上const纯属多此一举。

第二种写法和第三种写法本质上是一样的,在定义引用时加上const限制,目的都是不希望通过引用来修改原始数据的值

一.引用的基本用法

  1. #include <iostream>
  2. using namespace std;
  3.  
  4. int main(){
  5. int a = ;
  6. int &b = a;
  7. cout<<a<<", "<<b<<endl;
  8. cout<<&a<<", "<<&b<<endl;
  9.  
  10. return ;
  11. }

运行结果:
99, 99
0x28ff44, 0x28ff44

如果不希望通过引用修改原始数据的值,可以在定义时添加const限制:

  1. const int &b = a; // 或
  2. int const &b = a;

注意:引用在定义时需要添加&,在使用时不能添加&,使用时添加&表示取地址

二.引用作为函数参数

  1. #include <iostream>
  2. using namespace std;
  3.  
  4. void swap3(int &a, int &b);
  5.  
  6. int main(){
  7. int num1, num2;
  8.  
  9. cout<<"Input two integers: ";
  10. cin>>num1>>num2;
  11. swap3(num1, num2);
  12. cout<<num1<<" "<<num2<<endl;
  13.  
  14. return ;
  15. }
  16.  
  17. void swap3(int &a, int &b){
  18. int temp = a;
  19. a = b;
  20. b = temp;
  21. }

运行结果:

Input two integers: 12 34
12 34
Input two integers: 88 99
99 88
Input two integers: 100 200
200 100

三.引用作为函数返回值

引用除了可以作为函数形参,还可以作为函数返回值,请看下面的例子:

  1. #include <iostream>
  2. using namespace std;
  3. int &plus10(int &n){
  4. n = n + ;
  5. return n;
  6. }
  7. int main(){
  8. int num1 = ;
  9. int num2 = plus10(num1);
  10. cout<<num1<<" "<<num2<<endl;
  11. return ;
  12. }

运行结果:

20 20

注意:在将引用作为函数返回值时应该注意一个小问题,就是不能返回局部数据(例如局部变量局部对象局部数组等)的引用,因为当函数调用完成后局部数据就会被销毁,有可能在下次使用时数据就不存在了,C++ 编译器检测到该行为时也会给出警告。

因此像下面的写法是不正确的:

  1. #include <iostream>
  2. using namespace std;
  3. int &plus10(int &n){
  4. int m = n + ;
  5. return m; //返回局部数据的引用
  6. }
  7. int main(){
  8. int num1 = ;
  9. int num2 = plus10(num1);
  10. cout<<num2<<endl;
  11. int &num3 = plus10(num1);
  12. int &num4 = plus10(num3);
  13. cout<<num3<<" "<<num4<<endl;
  14. return ;
  15. }

不能将局部变量m返回!因为函数是在栈上运行的,并且运行结束后会放弃对所有局部数据的管理权,后面的函数调用会覆盖前面函数的局部数据。本例中,第二次调用 plus10() 会覆盖第一次调用 plus10() 所产生的局部数据,第三次调用 plus10() 会覆盖第二次调用 plus10() 所产生的局部数据。

C++语言基础(8)-引用的更多相关文章

  1. 《MSSQL2008技术内幕:T-SQL语言基础》读书笔记(下)

    索引: 一.SQL Server的体系结构 二.查询 三.表表达式 四.集合运算 五.透视.逆透视及分组 六.数据修改 七.事务和并发 八.可编程对象 五.透视.逆透视及分组 5.1 透视 所谓透视( ...

  2. 《MSSQL2008技术内幕:T-SQL语言基础》读书笔记(上)

    索引: 一.SQL Server的体系结构 二.查询 三.表表达式 四.集合运算 五.透视.逆透视及分组 六.数据修改 七.事务和并发 八.可编程对象 一.SQL Server体系结构 1.1 数据库 ...

  3. C#语言基础

    第一部分 了解C# C#是微软公司在2000年7月发布的一种全新且简单.安全.面向对象的程序设计语言,是专门为.NET的应用而开发的.体现了当今最新的程序设计技术的功能和精华..NET框架为C#提供了 ...

  4. C语言基础回顾

    第一章 C语言基础 1.  C语言编译过程 预处理:宏替换.条件编译.头文件包含.特殊符号 编译.优化:翻译并优化成等价的中间代码表示或汇编代码 汇编:生成目标文件,及与源程序等效的目标的机器语言代码 ...

  5. 黑马程序员_ C语言基础(二)

    ------Java培训.Android培训.iOS培训..Net培训.期待与您交流! ------- 概览 今天基础知识分为以下几点内容(注意:循环.条件语句在此不再赘述):   1.Hello W ...

  6. 【GoLang】GO语言系列--002.GO语言基础

    002.GO语言基础 1 参考资料 1.1 http://www.cnblogs.com/vimsk/archive/2012/11/03/2736179.html 1.2 https://githu ...

  7. Java学习总结(二)----Java语言基础

    1.     Java语言基础 2.1 关键字 定义:被java语言赋予特殊含义的单词 特点:关键字中的字母都为小写 用于定义数据类型的关键字 class,interface,byte,short,i ...

  8. php面试题之三——PHP语言基础(基础部分)

    三.PHP语言基础 1. strlen( )与 mb_strlen( )的作用分别是什么(新浪网技术部) strlen和mb_strlen都是用于获取字符串长度. strlen只针对单字节编码字符,也 ...

  9. Object Pascal 语言基础

    Delphi 是以Object Pascal 语言为基础的可视化开发工具,所以要学好Delphi,首先要掌握的就是Object Pascal 语言.Object Pascal语言是Pascal之父在1 ...

随机推荐

  1. [PKUSC2018]最大前缀和(DP)

    题意:求一个序列随机打乱后最大前缀和的期望. 考场上发现不管怎么设状态都写不出来,实际上只要稍微转换一下就好了. 一个前缀[1..k]是最大前缀,当且仅当前面的所有后缀[k-1,k],[k-2,k], ...

  2. UOJ Rounds

    UOJ Test Round #1 T1:数字比大小的本质是按(长度,字典序)比大小. T2:首先发现单调性,二分答案,用堆模拟,$O(n\log^2 n)$. 第二个log已经没有什么可优化的了,但 ...

  3. [xsy2300]好题

    题意:有一棵树,每个节点有颜色,要找出最小的连通块使得其中的点至少有$k$种不同的颜色,只需输出这个最小连通块的大小 因为$k$很小,所以如果颜色只有$k$种,我们可以直接状压DP,设$f_{i,j} ...

  4. 【字符串哈希】bzoj3555 [Ctsc2014]企鹅QQ

    枚举每个位置,给每个串的前半部分一个哈希值,后半部分一个哈希值,若是它们均相等,则视为这两个串相似. 每次转移之后,排序一下就行了. O(L*n*log(n)). #include<cstdio ...

  5. 键盘事件OnKeyListener

    1.效果图:就是在文本框中输入A,则显示A,输入B,则显示B.... (1)activity_main.xml <?xml version="1.0" encoding=&q ...

  6. 科研不是比赛,而是一种对未知和完美的自我追求——跟邢波(Eric Xing)面对面聊科研

    编者按:6月26日,2014年国际机器学习大会(ICML)在北京国际会议中心完美落幕.作为机器学习领域两大顶尖年会之一,这是 ICML大会30多年来首次来到中国和远东,在国内的机器学习界震动不小.身为 ...

  7. 蒙皮 skin

    http://help.autodesk.com/view/MAYAUL/2016/CHS/?guid=GUID-EFE68C08-9ADA-4355-8203-5D1D109DCC82 skin:顶 ...

  8. 理解JS里的偏函数与柯里化

    联系到上篇博客讲的bind完整的语法为: let bound = func.bind(context, arg1, arg2, ...); 可以绑定上下文this和函数的初始参数.举例,我们有个乘法函 ...

  9. http://blog.sina.com.cn/s/blog_62e1faba010147k4.html

    http://blog.sina.com.cn/s/blog_62e1faba010147k4.html

  10. 算法导论-求(Fibonacci)斐波那契数列算法对比

    目录 1.斐波那契数列(Fibonacci)介绍 2.朴素递归算法(Naive recursive algorithm) 3.朴素递归平方算法(Naive recursive squaring) 4 ...