什么是引用?
引用就是对变量起一个别名,而变量还是原来的变量,并没有重新定义一个变量。例如下面的例子:
 
 #include<iostream>
using namespace std; int main()
{
int a = ;
int& n = a;
cout<<a<<endl;
cout<<n<<endl;
cout<<&a<<endl;
cout<<&n<<endl; return ;
}

程序的运行结果为:

我们可以看到变量a和变量a的引用(别名)n所指向的就是同一片空间,而且别名n并没有创建一个新的变量
 
在引用的时候我们应该注意一些问题:
1.一个变量可以有多个别名
2.引用必须初始化
3.引用只可以在变量初始化的时候引用一次,之后不可以在引用其他的变量(这个想要引用其他的变量几乎是无法实现,反正我没办法)
 常引用
现在我们了解了什么是引用,而常引用是非常容易出现错误的一种引用,下面我们展开讨论
以下代码就是相关的用法:
 int main()
{
int d1 = ;
const int & d2 = d1;
d1 = ; // d1改变d2的值也会改变。
// d2 = 6; // 不能给常量(不能被修改的量)赋值
const int d3 = ;
const int & d4 = d3;
// int&d5 = d3;
const int & d6 = ; // 常量具有常性,只有常引⽤可以引⽤常量
double d7 = 1.1;
// int& d8 = d7; //d7是double类型,d8是int,d7赋值给d8时要生成一个临时变量
//也就是说d8引⽤的是这个带有常性的临时变量,所以不能赋值。
const int& d9 = d7;
return ;
}
 
从以上的代码中我们就可以知道const引用时应该注意的问题。
 
引用可以作为函数的参数也可以作为函数的返回值来使用,但是我们在使用的时候应该注意些什么呢?
1.引用作为函数的参数时
       在函数传参的时候,在C语言中有两种方式,一种是值传递,还有一种是址传递,也就是指针传递,而在C++中我们则引入了引用传递。这三种传递的方式各有各的特点的,这里我们着重说一下引用传递的特点
 #include<iostream>
using namespace std;
#include <Windows.h>
struct BigData
{
int array [];
};
void DealBigData1(BigData& x)
{
x.array[] = ;
x.array[] = ;
x.array[] = ;
}
void DealBigData2 (BigData x)
{
x.array []= ;
x.array []= ;
x.array []= ;
}
void TestReference()
{
BigData bd ;
int begin = GetTickCount ();
for (int i = ; i < ; ++i )
{
DealBigData1(bd);
}
int end = GetTickCount ();
cout<<"cost time:" <<end - begin<<endl ;
begin = GetTickCount ();
for (int i = ; i < ; ++i )
{
DealBigData2(bd);
}
end = GetTickCount ();
cout<<"cost time:" <<end - begin<<endl ;
}
int main()
{
TestReference();
return ;
}
以上代码的运行结果为:
 
 
从运行结果我们不难看出相比于传值而言,传引用无疑极大地提升了程序的性能。
 
2.引用作为函数的返回值时
 
 int& Add (int d1, int d2)
{
int ret = d1 + d2;
return ret ;
}
void test()
{
int a = , b = ;
int c = Add( a, b );
cout<<"c:" <<c<< endl;
}
上面这段代码是错误的用法,因为用引用接收了一个局部或临时变量的地址,在我们编译的时候回报出如下的警告:
 
 
       这里是因为函数在返回的时候会创建一个临时变量,而我们在以引用作为函数的返回值的时候,引用的是这个临时变量,我们都知道临时变量在函数运行完毕后会销毁的,那样这种写法毫无疑问是错误的不推荐的。
而下面的代码则是以传值作为函数的返回值,是正确的,当我们要以引用作为函数的返回值的时候,我们应该return一个以引用传递的参数,那样也就是正确的。
 int Add1 (int a, int b)
{
int ret = a + b;
return ret;
}
int& Add2(int& a, int b)
{
int ret = a + b;
return ret;
}
void test1()
{
int ret = Add1(, );
cout<<"ret:" <<ret<< endl;
}
void test2()
{
int a = , b = ;
int c = Add2( a, b );
cout<<"c:" <<c<< endl;
}
int main ()
{
test1();
test2();
return ;
}
 
我们查看上面两个函数以传值作为函数返回值和传引用作为函数返回值时的汇编有何不同,如下图:

我们不难发现传值返回的时候是把ret的值放入了eax寄存器中,而传引用返回的时候是把ret的地址放进了eax寄存器中。
因此我们应该在使用引用作为函数的返回值的时候应该注意:
1.不要返回⼀个临时变量的引⽤。
2. 如果返回对象出了当前函数的作⽤域依旧存在,则最好使⽤引⽤返回,因为这样更⾼效
 
在C语言中有指针,而C++中有应用,那么指针与引用究竟有什么区别与联系呢?
1. 引⽤只能在定义时初始化⼀次,之后不能改变指向其它变量(从⼀⽽终);指
针变量的值可变。
2. 引⽤必须指向有效的变量,指针可以为空。
3. sizeof指针对象和引⽤对象的意义不⼀样。 sizeof引⽤得到的是所指向的变量的
⼤⼩,⽽sizeof指针是对象地址的⼤⼩。
4. 指针和引⽤⾃增(++)⾃减(--)意义不⼀样。
5. 相对⽽⾔,引⽤⽐指针更安全。
所以在使用指针和引用的时候我们应该知道指针虽然⽐引⽤更灵活,但是也更危险。使⽤指针时⼀定要注意检查指针是否为空。指
针所指的地址释放以后最好置0,否则可能存在野指针问题。
 
 

C++基础之引用与指针的区别与联系、常引用使用时应注意的问题的更多相关文章

  1. c++中的引用与指针的区别

    http://blog.csdn.net/lyd_253261362/article/details/4323691 c++中的引用与指针的区别 ★ 相同点: 1. 都是地址的概念: 指针指向一块内存 ...

  2. C++中引用与指针的区别(详细介绍)

    C++中引用与指针的区别(详细介绍) C++中的引用与指针的区别   指向不同类型的指针的区别在于指针类型可以知道编译器解释某个特定地址(指针指向的地址)中的内存内容及大小,而void*指针则只表示一 ...

  3. c++引用与指针的区别

    c++引用与指针的区别 ★ 相同点: 1. 都是地址的概念: 指针指向一块内存,它的内容是所指内存的地址:引用是某块内存的别名. 指针的权威定义: In a declaration T D where ...

  4. [ZZ]C++中,引用和指针的区别

    (1) 引用总是指向一个对象,没有所谓的 null reference .所有当有可能指向一个对象也由可能不指向对象则必须使用 指针. 由于C++ 要求 reference 总是指向一个对象所以 re ...

  5. Java中到底有没有指针;同时注意引用和指针的区别

    Java中引用的作用类似于指针,但是有区别:()    (1) 指针必然指向一个内存地址,如果你定义的时候不指定,就会乱指(很可能造成安全隐患)但是引用定义出来后默认指向为空.     (2) 指针可 ...

  6. C、C++中引用与指针的区别

    1:引用的和指针在概念上的区别 引用是变量的别名,例如 int m; int &n=m; 引用作为一个别名.它在逻辑上不是独立的,它的存在具有依附性,所以引用必须在一开始就被初始化,而且其引用 ...

  7. 引用的作用&引用与指针的区别

    引入 C语言中函数有两种传参的方式: 传值和传址.以传值方式, 在函数调用过程中会生成一份临时变量用形参代替, 最终把实参的值传递给新分配的临时变量即形参. 它的优点是避免了函数调用的一些副作用, 但 ...

  8. C语言学习笔记 (002) - C++中引用和指针的区别(转载)

    下面用通俗易懂的话来概述一下: 指针-对于一个类型T,T*就是指向T的指针类型,也即一个T*类型的变量能够保存一个T对象的地址,而类型T是可以加一些限定词的,如const.volatile等等.见下图 ...

  9. <转>c++引用与指针的区别(着重理解)

     ★ 相同点: 1. 都是地址的概念: 指针指向一块内存,它的内容是所指内存的地址:引用是某块内存的别名.  ★ 区别: 1. 指针是一个实体,而引用仅是个别名: 2. 引用使用时无需解引用(*),指 ...

随机推荐

  1. 【JAVAWEB学习笔记】20_增删改查

    今天主要是利用三层架构操作数据库进行增删查改操作. 主要是编写代码为主. 附图: 前台和后台 商品的展示 修改商品

  2. CI 经常失败?可能是这 5 大原因…

    本文翻译自文章 Top 5 Reasons for CI Failure,主要介绍了 CI 失败的五个原因,包括 CI 服务的错误选择.CI 工程师的不专业性.随意更改CI服务器配置.CI服务器性能差 ...

  3. 数据结构与算法系列研究五——树、二叉树、三叉树、平衡排序二叉树AVL

    树.二叉树.三叉树.平衡排序二叉树AVL 一.树的定义 树是计算机算法最重要的非线性结构.树中每个数据元素至多有一个直接前驱,但可以有多个直接后继.树是一种以分支关系定义的层次结构.    a.树是n ...

  4. 为什么字符串会有length属性-JS中包装对象

    任何原始类型的数据  (primitive type) 比如 String类型的字符串 "abcd"   "abcd"  是原始类型的数据 但是 当他调用 le ...

  5. java面向对象--抽象类和接口

    如果某个父类只知道其子类应该包含哪些方法,但无法知道如何实现这些方法,同时要使用多态的特性,怎么办? 抽象方法:关键字abstract允许在一个类中创建一个或多个没有方法体的方法--只提供方法签名,但 ...

  6. Codeforces Round #392 (Div. 2)

    D题,给出n,k,k是n进制数,但是大于十进制时,它的表示方法仍为十进制那种,比如16进制下的15,我们可以看成就是15,或者1|5,也就是1×16+5 = 21,让你求出能表达的最小十进制数 从后面 ...

  7. 使用FileUtils简化你的文件操作

    前言: 在工作当中我们往往遇到很多文件的操作,我们也习惯写一些自己定义的工具类来简化文件操作,其实apache的commons的FileUtils类就是这样一个工具类,使用它能大大的简化我们对文件的操 ...

  8. 【js实例】js中的5种基本数据类型和9种操作符

    js中的5中基本数据类型 js标识符 第一个字符必须为字母,下划线,或美元符 其他字符可以是字母,下划线,美元符,数字 js标识符区分大小写 标识符不能使关键字和保留字 关键字: break do i ...

  9. Mac主机映射到域名

    1, control+space  打开spotlight, 搜索"终端" 2, 打开终端 3, 在"终端"界面中输入: sudo vi /etc/hosts ...

  10. hadoop2.7.2单机与伪分布式安装

    环境相关 系统:CentOS 6.8 64位 jdk:1.7.0_79 hadoop:hadoop 2.7.2 安装java环境 详见:linux中搭建java开发环境 创建hadoop用户 # 以r ...