什么是引用?
引用就是某一变量或者某一目标的别名。对引用的操作就是对实际变量的操作。引用的声明方式:类型标识符 &引用名=目标变量名。
(1)&在此不是求地址运算,而是起标识作用。
(2)类型标识符是指目标变量的类型。
(3)声明引用时,必须同时对其进行初始化。
(4)引用声明完毕后,相当于目标变量名有两个名称,即该目标原名称和引用名,且不能再把该引用名作为其他变量名的别名。
int a,&ra=a;
a为目标原名称,ra为目标引用名。给ra赋值:ra=1; 等价于 a=1;
(5)对引用求地址,就是对目标变量求地址。&ra与&a相等。即我们常说引用名是目标变量名的一个别名。别名一词好像是说引用不占据任何内存空间。但是编译器在一般将其实现为const指针,即指向位置不可变的指针。即引用实际上与一般指针同样占用内存。
(6)不能建立引用的数组。因为数组是一个由若干个元素所组成的集合,所以无法建立一个由引用组成的集合。但是可以建立数组的引用.
例如: int& ref [3]= {2,3,5};//声明ref引用的数组错误
但是可以这样写:
const int (&ref)[3] ={2,3,5};
为什么要加上const ,因为{2,3,5}此时是个字面值数组,是保存在代码段里,只读的属性,如果不加,编译错误,而且后面对ref[0]的赋值也不会成功.
需要特别强调的是引用并不产生对象的副本,仅仅是对象的同义词。
(7)引用必须在定义时马上被初始化,因为它必须是某个东西的同义词。你不能先定义一个引用后才
初始化它。例如下面语句是非法的:
Point &pt3;
pt3=pt1;
(8)
引用是除指针外另一个可以产生多态效果的手段。
这意味着,一个基类的引用可以指向它的派生类实例。例如:
class A;
class B: public A
{
...
};
B b;
A & aRef = b; // 基类引用指向派生类
如果A类中定义有虚函数,并且在B类中重写了这个虚函数,就可以通过aRef产生多态效果。
下面是引用的使用例子,说明都在代码注释里了。
#include <iostream>
using namespace std;
void swap1(int a,int b);
void swap2(int* a,int* b);
void swap3(int& a,int& b);
void swap4(const char* a,const char* b);
void swap5(const char** a,const char** b);
void swap6(const char*& a,const char*& b);
int main()
{
int a = 10,b = 20;
swap1(a,b);
cout<<"swap1"<<" : "<<a<<" , "<<b<<endl; //输出10,20;
swap2(&a,&b);
cout<<"swap2"<<" : "<<a<<" , "<<b<<endl; //20,10
swap3(a,b);
cout<<"swap3"<<" : "<<a<<" , "<<b<<endl; //10,20 因为swap2已经交换了;
const char* pa = "hello";
const char* pb = "world";
swap4(pa,pb);
cout<<"swap4"<<" : "<<pa<<" , "<<pb<<endl; //hello,world;
swap5(&pa,&pb);
cout<<"swap5"<<" : "<<pa<<" , "<<pb<<endl; //world,hello;
swap6(pa,pb);
cout<<"swap6"<<" : "<<pa<<" , "<<pb<<endl; //world,hello;
system("pause");
return 0;
}
//值传递,只是形参的交换,并没有实现实参的交换;
void swap1(int a,int b)
{
int c = a;
a = b;
b = c;
}
//形参指向的是实参的地址,直接对实参地址内容的交换就是实参值的交换;
void swap2(int* a,int* b)
{
int c = *a;
*a = *b;
*b = c;
}
//引用交换,形参引用就是实参的别名,引用实质是指针,看上去交换的是形参的值,实际上交换的就是实参;
void swap3(int& a,int& b)
{
int c = a;
a = b;
b = c;
}
//因为实参本身就是指针,所以仍然是值传递,并没有对实参的地址交换;
void swap4(const char* a,const char* b)
{
const char* c = a;
a = b;
b = c;
}
//传递实参的地址,完成实参值的交换;
void swap5(const char** a,const char** b)
{
const char* c = *a;
*a = *b;
*b = c;
}
//使用指针的引用,实际上交换的就是实参;
void swap6(const char*& a,const char*& b)
{
const char* c = a;
a = b;
b = c;
}
//判断指针和引用的时候,需要从右向左读 例如 char ** a 则 a 是一个指针,指向另一个指针,而另一个指针指向的是char;
//const char*& b 则 b 是一个引用,是一个指针的引用,而指针指向的是一个 const char;
//引用的作用一般是为了节约效率,例如函数传递的参数是结构体,或者类,那么如果进行值传递,性能就比较低;
//但是需要注意的是,引用一般搭配const类型一起使用。因为这样可以避免在参数传递时,由于程序员的失误导致的实参值篡改;
//另外,引用还被用于函数的输出参数;
//指针方式;
double calcircle1(double r,double* area)
{
*area = 3.14 * r * r; //圆的面积;
return 2 * 3.14 * r; //圆的周长;
}
//调用方式;
double area;
double c = calcircle1(3,&area);
//引用方式;
double calcircle2(double r,double& area)
{
area = 3.14 * r * r; //圆的面积;
return 2 * 3.14 * r; //圆的周长;
}
//调用方式;
double area;
double c = calcircle2(3,area);