标题：引用类型
引用类型 (reference type)
“引用”（reference）是c++的一种新的变量类型，是对C的一个重要补充。它的作用是为变量起一个别名。假如有一个变量a，想给它起一个别名，可以这样写：
int a;int &b=a;
这就表明了b是a的“引用”，即a的别名。经过这样的声明，使用a或b的作用相同，都代表同一变量。在上述引用中，&是“引用声明符”，并不代表地址。
不要理解为“把a的值赋给b的地址”。引用类型的数据存储在内存的堆中，而内存单元中只存放堆中对象的地址。声明引用并不开辟内存单元，b和a都代表同一变量单元。
注意：在声明引用变量类型时，必须同时使之初始化，及声明它代表哪一变量。在声明一个变量的引用之后，在本函数执行期间，该引用一直与其代表的变量相联系
，不能再作为其他变量的别名。下面的用法不对：
int a1,a2;
int &b=a1;
int &b=a2;//企图使b变成a2的别名（引用）是不行的。这样是错误的。
我们可以把a2的值赋给b。
b=a2;
引用和指针的区别
看实例吧：
引用是C++中的概念，初学者容易把引用和指针混淆一起。
下面的程序中，n是m的一个引用（reference），m是被引用物（referent）。
int m;
int &n = m;
n相当于m的别名（绰号），对n的任何操作就是对m的操作。
所以n既不是m的拷贝，也不是指向m的指针，其实n就是m它自己。
引用的规则
（1）引用被创建的同时必须被初始化（指针则可以在任何时候被初始化）。
（2）不能有NULL引用，引用必须与合法的存储单元关联（指针则可以是NULL）。
（3）一旦引用被初始化，就不能改变引用的关系（指针则可以随时改变所指的对象）。
以下示例程序中，k被初始化为i的引用。
语句k = j并不能将k修改成为j的引用，只是把k的值改变成为6。
由于k是i的引用，所以i的值也变成了6。
int i = 5;
int j = 6;
int &k = i;
k = j; // k和i的值都变成了6；
引用的主要功能
引用的主要功能：传递函数的参数和返回值。
C++语言中，函数的参数和返回值的传递方式有三种：值传递、指针传递和引用传递。
以下是"值传递"的示例程序。
由于Func1函数体内的x是外部变量n的一份拷贝，改变x的值不会影响n, 所以n的值仍然是0。
void Func1(int x)
{
x = x + 10;
}
...
int n = 0;
Func1(n);
cout << "n = " << n =" 0" n =" 0;" n = " << n << endl; // n = 10 以下是" size="14">
void Func3(int &x) { x = x + 10; } ... int n = 0; Func3(n); cout << "n = " << n =" 10">
（1） 在实际的程序中，引用主要被用做函数的形式参数--通常将类对象传递给一个函数.引用必须初始化. 但是用对象的地址初始化引用是错误的，我们可以定义一个指针引用。
1 int ival = 1092;
2 int &re = ival; //ok
3 int &re2 = &ival; //错误
4 int *pi = &ival;
5 int *&pi2 = pi; //ok
（2） 一旦引用已经定义，它就不能再指向其他的对象.这就是为什么它要被初始化的原因。
（3） const引用可以用不同类型的对象初始化(只要能从一种类型转换到另一种类型即可)，也可以是不可寻址的值，如文字常量。例如
double dval = 3.14159;
//下3行仅对const引用才是合法的
const int &ir = 1024;
const int &ir2 = dval;
const double &dr = dval + 1.0;
上面，同样的初始化对于非const引用是不合法的，将导致编译错误。原因有些微妙，需要适当做些解释。
引用在内部存放的是一个对象的地址，它是该对象的别名。对于不可寻址的值，如文字常量，以及不同类型的对象，编译器为了实现引用，必须生成一个临时对象，引用实际上指向该对象，但用户不能访问它。
例如:
double dval = 23;
const int &ri = dval;
编译器将其转换为:
int tmp = dval; // double -> int
const int &ri = tmp;
同理：上面代码
double dval = 3.14159;
//下3行仅对const引用才是合法的
const int &ir = 1024;
const int &ir2 = dval;
const double &dr = dval + 1.0;
内部转化为：
double dval = 3.14159;
//不可寻址，文字常量
int tmp1 = 1024;
const int &ir = tmp1;
//不同类型
int tmp2 = dval;//double -> int
const int &ir2 = tmp2;
//另一种情况，不可寻址
double tmp3 = dval + 1.0;
const double &dr = tmp3;
（4） 不允许非const引用指向需要临时对象的对象或值，即，编译器产生临时变量的时候引用必须为const!!!!切记！！
int iv = 100;
int *&pir = &iv;//错误，非const引用对需要临时对象的引用
int *const &pir = &iv;//ok
const int ival = 1024;
int *&pi_ref = &ival; //错误，非const引用是非法的
const int *&pi_ref = &ival; //错误，需要临时变量，且引用的是指针，而pi_ref是一个非常量指针
const int * const &pi_ref = &ival; //正确
//补充
const int *p = &ival;
const int *&pi_ref = p; //正确
（5） ********对于const int *const & pi_ref = &iva; 具体的分析如下：*********
1.不允许非const引用指向需要临时对象的对象或值
int a = 2;
int &ref1 = a;// OK.有过渡变量。
const int &ref2 = 2;// OK.编译器产生临时变量，需要const引用
2.地址值是不可寻址的值
int * const &ref3 = &a; // OK;
3.于是，用const对象的地址来初始化一个指向指针的引用
const int b = 23;
const int *p = &b;
const int *& ref4 = p;
const int *const & ref5 = &b; //OK
const引用的语义到底是什么？
最后，我们可能仍然不明白const引用的这个const的语义是什么
const引用表示，试图通过此引用去(间接)改变其引用的对象的值时，编译器会报错！
这并意味着，此引用所引用的对象也因此变成const类型了。我们仍然可以改变其指向对象的值，只是不通过引用
下面是一个简单的例子：
1 #include<iostream>
2 using namespace std;
3
4 int main()
5 {
6 int val = 1024;
7 const int &ir = val;
8
9 val++;
10 //ir++;
11
12 cout <<"val="<<val<<"\n";
13cout<<"ir="<<ir;
14 return 0;
15 }
其中第10行，如果我们通过ir来改变val的值，编译时会出错。但是我们仍然可以通过val直接改变其值(第9行)
总结：const引用只是表明，保证不会通过此引用间接的改变被引用的对象！
另外，const既可以放到类型前又可以放到类型后面，放类型后比较容易理解：
string const *t1;
const string *t1;
typedef string* pstring;string s;
const pstring cstr1 = &s;就出错了
但是放在类型后面不会出错:
pstring const cstr2 = &s;
引用在类中的使用
1. #include <iostream>
2. using namespace std;
3.
4. class A
5. {
6. public:
7.     A(int i=3):m_i(i){}
8.     void print()
9.     {
10.         cout<<"m_i="<<m_i<<endl;
11.     }
12. private:
13.     int m_i;
14. };
15.
16. class B
17. {
18. public:
19.     B(){}
20.     B(A& a):m_a(a){}
21.     void display()
22.     {
23.         m_a.print();
24.     }
25. private:
26.     A& m_a;
27. };
28.
29.
30. int main(int argc,char** argv)
31. {
32.     A a(5);
33.     B b(a);
34.     b.display();
35.     return 0;
36. }
引用在类中使用需注意
其中，要注意的地方就是引用类型的成员变量的初始化问题,它不能直接在构造函数里初始化，必须用到初始化列表，且形参也必须是引用类型。
凡是有引用类型的成员变量的类，不能有缺省构造函数。原因是引用类型的成员变量必须在类构造时进行初始化。
如果两个类要对第三个类的数据进行共享处理，可以考虑把第三个类作为这两个类的引用类型的成员变量