二、指针的好基友的&
1.&的意义。说&是指针的好基友其实不恰当,因为&这个符号在C/C++不止有一种含义,但是因为其经常会和指针一起出现在被问的问题列表上,所以,在大部分情况下,它们是好基友,那么&符号一共有哪些涵义呢?这一般都是初级筛选的题目,这种题目的意义在于快速的筛选掉那些根本什么也不会的人。答案很简单,主要有三个地方会用到这个符号,第一个取变量的地址,比如在int *pointer=&i;时,这是这个符号是出现在等号的右边(也就是右值),第二个表示引用,这个概念会是本节的重点,出现在int &ref=i;这种类型的等式之中,在等号的左边,第三种是一种位运算符,标示两个位相与(1&1=1,1&0=0,0&1=0,0&0=0)。
2.什么是“引用”。引用这个词可以理解为精确无误的转述或者表达别人曾经说过的话或者写过的文字,说白了完全就是别人的东西,那么怎么理解引用这个东西呢?按照很多经典书籍上所叙述的,引用就可以看做是变量的一个别名(alias),可以理解成换了另外一个符号表示这个变量。在编译器编译你的程序的时候,会将你在程序里定义的所有符号放在一个叫做符号表的物体之中,然后按照一定的规律给符号表中的内容分配内存。比如你定义了一个int i=3;那么这个i就会被放在符号表中,然后会给这个符号表示的内容分配一个内存单元,其中的内容是3,再按照某种深刻的方式将这个分配的内存和这个符号联系起来,这就完成了一个变量的定义(编译原理只记得个大概了,有错误的话请指正)。对比指针和引用的使用方式,多少有点类似,那么先从下面的一个小例子初窥一下指针和引用在这个方面有什么不同:
int i=0; int *pointer_i=&i; int &ref_i=i; cout<<"address of i:"<<&i<<endl; cout<<"address of ref_i:"<<&ref_i<<endl; cout<<"address of pointer_i:"<<&pointer_i<<endl;
这里面出现了太多&符号,参考1里面的内容,主要有两个含义,一个是取变量地址,比如cout里面那些,pointer的那句,一个是引用,分清楚这些应该并不是什么难事,运行这段程序,可以看到输出如下:
可以看到ref_i和i的地址是一样的,pointer的地址不一样,说明了编译器给pointer分配了一个内存单元,而ref_i没有,这里就是它们的第一个不同点,编译器会给指针分配一个内存单元,而对于引用不会,所以说ref_i所表示都不能称之为一个变量或什么的,它仅仅是i的另一个符号表示而已。它和i一样,一举一动都是操作的同一个内容,完成的同一件事情。那么设计这样一个概念的作用是什么呢?在上面这段程序中使用两个符号表示一个变量的意义明显不是要一个做另一个的备胎,其作用主要体现在涉及到函数的时候(包括成员函数),下面一个例子真的是烂大街了。
void swap(int& i, int& j)
{
int tmp = i;
i = j;
j = tmp;
}
如果你看过100页的关于C++的书,你会像背诵一样说出上面代码的意义,它可以完成两个数的交换,如果不使用&,就不可能得到正确的结果。为了稍微深刻一点的展示这个概念,可以采用如下的代码:
void swap1(int& i, int& j) { cout<<"1:address1:"<<&i<<endl; cout<<"1:address2:"<<&j<<endl; int tmp = i; i = j; j = tmp; } void swap2(int i, int j) { cout<<"2:address1:"<<&i<<endl; cout<<"2:address2:"<<&j<<endl; int tmp = i; i = j; j = tmp; } void main() { int a=7,b=10; cout<<"address of a:"<<&a<<endl; cout<<"address of b:"<<&b<<endl; swap1(a,b); swap2(a,b); }