引用与指针
指针和引用一直是C++中难懂的部分,为此我也困惑了很久,下面说说我对引用和指针的简单理解。
在使用函数时我们常常会纠结实参传递到形参后,函数对形参的操作会不会改变实参的值(也就是主函数的相应变量),最典型的例子是swap(int a,int b)。我们都知道,函数在调用时会给变量重新开辟一个存储空间,而这个存储空间会暂时存储形参的值,如果函数在调用完毕后,其相应存储空间的值会被释放。例如下面一段代码:
void swap1(int a, int b) { int temp = 0; temp = a; a = b; b = temp; } void swap2(int *a, int *b) { int temp; temp = *a; *a = *b; *b = temp; } int main() { int i = 3, j = 8; swap1(i, j); swap2(&i, &j); return 0; }
当主函数调用swap1(int a, int b)时,变量a,b会被放到一个存储空间中,而这个存储空间和原来的i,j存储空间没有关系。函数执行完毕后,a,b被临时存放的空间会被释放,也就是说原来a,b的值也不会存在,因此这个函数不会影响主函数中i,j的值,因为这个函数没有对i,j的相应地址进行相应操作。程序中只有对变量的地址进行操作时,其变量的值才会发生改变。(简单理解)。
在函数swap2(int *a, int *b)中,由于函数中的形参就是i,j的地址,因此对地址进行操作(函数中是对地址存放的变量值进行操作)就会改变实参的值。而引用的实质就是直接对变量的地址进行操作,因此引用也能改变实参的值。指针和引用在很多时候具有相同的功能,但两者也有一定的区别,这在其他的地方也能查到。下面讨论更为复杂点的情况。
typedef struct TreeNode { char val; TreeNode *left; TreeNode *right; }*Tree; void creat(Tree &T) { char val=' '; cin >> val; if (val == '#') T = NULL; else { T = new(TreeNode); T->val = val; creat(T->left); creat(T->right); } }
上面是建立二叉树的代码。creat(Tree &T)形参为引用,而不是指针。不能用指针的原因是形参为指针的话,传递的进去的是指针所指向的变量的地址,也就是T所指向的地址,函数在建立完链表后,主函数中指针T本身的值不会被改变,因此我们不能得到函数中建立的二叉树,因为指针本身T的值没有改变,只是T所指对象的值发生了改变。这点和swap函数是一致的,而引用却可以改变主函数中T的值。如果想用指针进行操作的话,可以使用指向指针的指针,也就是要对指针T的地址而不是T所指对象的地址进行操作,这样才能在函数中改变实参的值。简单的说,函数中形参只有是对地址进行操作时才能改变实参的值。
另外,在C++中取地址和引用符号相同,简单的区别方法是引用符号前面一半是类型名,而取地址时,符号后面是变量。