什么是引用?
引用不是重新定义一个变量,而是给已经定义好的变量起了别名。
定义的格式为:
类型 &引用变量名 = 已定义过的变量名;
如下代码:
#include<iostream>
using namespace std;
int main()
{
int a = 10;
int& n = a;
cout<<a<<endl;
cout<<n<<endl;
cout<<&a<<endl;
cout<<&n<<endl;
return 0;
}
运行后的结果为:
由此可见
变量a和变量a的引用(别名)n所指向的就是同一片空间,而且别名n并没有创建一个新的变量。
引用有以下特点
1.一个变量可以取多个别名;
2.引用必须初始化;
3.引用只能在初始化时引用一次,不能再改为引用其他变量。
常引用
以上是对引用的基本介绍,下面介绍一种非常容易出错的引用——常引用
直接看代码
#include<iostream>
using namespace std;
int main()
{
int d1 = 4;
const int & d2 = d1;
d1 = 5; // d1改变 d2的值也会改变。
//d2 = 6; // 不能给常量(不能被修改的量)赋值
const int d3 = 1;
const int & d4 = d3;
//int&d5 = d3;
const int & d6 = 5; // 常量具有常性,只有常引用可以引用常量
double d7 = 1.1;
//int& d8 = d7; //d7是double类型,d8是int,d7赋值给 d8时要生成一个临时变量
// 也就是说d8引用的是这个带有常性的临时变量,所以不能赋值。
const int& d9 = d7;
return 0;
}
引用可以作为函数参数和函数返回值来用,那么在使用的时候要注意些什么呢?
1.引用作为函数参数时
在函数传参中,我们在C语言部分学习两种传递方法,一种是值传递,另一种是址传递,也是就指针用作函数参数,那么在c++部分我们将引入引用传递。这三种传递方式各有各的特点,在这里,着重分析一下引用传递。
直接上代码
#include<iostream>
using namespace std;
#include <Windows.h>
struct BigData
{
int array [1000];
};
void DealBigData1(BigData& x)
{
x.array[0] = 0;
x.array[1] = 1;
x.array[2] = 2;
}
void DealBigData2 (BigData x)
{
x.array [0]= 0;
x.array [1]= 1;
x.array [2]= 2;
}
void TestReference()
{
BigData bd ;
int begin = GetTickCount ();//GetTickCount 得到开始时间
for (int i = 0; i < 1000000; ++i )
{
DealBigData1(bd);
}
int end = GetTickCount ();//得到结束时间
cout<<"cost time:" <<end - begin<<endl ;
begin = GetTickCount ();
for (int i = 0; i < 1000000; ++i )
{
DealBigData2(bd);
}
end = GetTickCount ();
cout<<"cost time:" <<end - begin<<endl ;
}
int main()
{
TestReference();
return 0;
}
代码运行结果
从运行结果我们不难看出相比于传值而言,传引用无疑极大地提升了程序的性能。
2.引用作为函数返回值
#include <iostream>
using namespace std;
int& Add(int a, int b)
{
int ret = a + b;
return ret;
}
int main()
{
int a = 3;
int b = 4;
int ret = Add(a, b);
cout<<ret<<endl;
return 0;
}
这段代码,在编译时报出如下警告
这是因为在函数返回时会创建一个临时变量,而我们将引用作为函数返回值时,引用的是这个临时变量,临时变量会在函数结束后销毁,因此这种写法是不推荐的。
下面将对比一下个函数以传值作为函数返回值和传引用作为函数返回值的不同
先上代码
#include <iostream>
using namespace std;
int c;
int Add1 (int a, int b)
{
int ret = a + b;
return ret;
}
int& Add2(int& a, int b)
{
c = a + b;
return c;
}
void test1()
{
int ret = Add1(1, 2);
cout<<"ret:" <<ret<< endl;
}
void test2()
{
int a = 3, b = 4;
int d = Add2( a, b );
cout<<"d:" <<d<< endl;
}
int main ()
{
test1();
test2();
return 0;
}
通过查看汇编语言发现
传值的时候我们是将ret的值放在了eax寄存器中,传引用的时候我们是将ret的地址放在了eax寄存器中
因此我们在将引用作为函数返回值的时候,要注意一下几点
1.首先不要返回一个临时变量的引用
2.如果返回对象出了这个作用域后依然存在,那么尽量使用引用返回,因为这样更高效。
在C语言中有指针,而C++中有应用,那么指针与引用究竟有什么区别与联系呢?
1.引用必须在创建的时候初始化一次,且之后不能改指其他变量,而指针的值可以改变;
2.引用指向的变量必须是有效的变量,而指针可以为空;
3.sizeof指针对象和引用对象的意义不一样,sizeof引用对象,得到的是引用对象指向变量的大小,而sizeof指针,得到的是对象地址的大小;
4.指针和引用的对象的自增和自减意义不同;
5.相对而言,引用比指针更加安全。
总而言之
指针比引用更加灵活,也更加危险,使用指针时一定要先判断是否为空,指针所指向的地址释放后,要置为空,否则可能存在野指针的问题。