赞
踩
通过本文探究指针引用传参和指针传参的差异,以及引用的特性。
最近有位同学找到我,说他在学习树的过程中遇到一个问题,冥思苦想了几个小时都不得解。
这个问题是这样的,他通过广义表创建一棵树,再遍历输出时却得到的是空值。先序遍历的函数经过测试没有问题,广义表表示也没问题,那问题肯定就在建树环节。
他的建树代码段是这样的:(还没学到树的可以跳到后面)
主函数:
- int main()
- {
- BinaryTree<char> T;
- const char array[] = "A(B,C)";
- T.CreateBinTree(T.getRoot(), array);
- T.PreOrderTraverse(T.getRoot());
- return 0;
- }
获取根结点:
BinTreeNode<T>* getRoot() { return root; }
建树:
- template<class T>
- void BinaryTree<T>::CreateBinTree(BinTreeNode<T>* root,const char* array) {
- LinkStack< BinTreeNode<T>*> stack;
- BinTreeNode<T>* p ,*t;
- root = NULL;
- int k=0;//k=1左子树 k=2右子树
- int i = 0;
-
- while (array[i]) {
- switch (array[i]) {
- case ' ':
- break;
- case '(': {
-
- stack.Push(p);
- k = 1;
- break;
- }
- case ',': {
- k = 2;
- break;
- }
- case ')': {
-
- stack.Pop(t);
- break;
- }
- default:
- p = new BinTreeNode<T>(array[i]);
- if (root == NULL)root = p;
- else {
- if (k == 1) {
- t=stack.getTop();
- t->lchild = p;
-
- }
- else {
- t=stack.getTop();
- t->rchild = p;
- }
- }
- }
- i++;
- }
- }
总的来说就是传入树根,根据广义表的字符串如"A(B,C)"来建树
看起来建树的过程没有什么问题,但是分别在建树函数体中和主函数中输出一次root的值,却得到了这样的结果:
不会树的同学看这里,这个问题简单说就是传入指针root,在函数中对root进行操作,但并没有改变实际参数root。
这其实是部分初学者的一个误解,认为传入指针就能一定修改与该指针相关的变量的值,实际上向函数传入指针,指针形参和实参有同个值(变量地址),所以能通过地址对所指变量进行修改,但它们本身仍遵循函数参数传递的规则,即函数内的指针形参改变了值(形参指针指向了另一个变量),实参指针的值(指向)不会改变。
建树的函数中
- p = new BinTreeNode<T>(array[i]);
- if (root == NULL)root = p;
这两句正是改变了形参的指向,但实参的root指向不变,所以形参建的树没有传到外面。
要使函数内部的形参指针指向改变,实参指针也随之改变,很容易想到指针引用传参,引用是给变量起个别名,函数用到引用传参时,在函数内改变了形参的值,实参也会改变。
将建树函数这样修改:
void BinaryTree<T>::CreateBinTree(BinTreeNode<T>* &root,const char* array)
于是形参便成为了对实参的引用。我以为我行了,一运行,出现这个错误:
关于题目中的“无法将参数从int*转换为int*&”问题,与这个类似,出现这种情况一般是将一个函数的返回值(非引用返回)作为参数直接传入一个形参为引用变量的函数中。int*和int* &尽管返回的值是相同的,但int*就仅仅只是返回一个值这个值本身没有载体,除非用一个变量去接收它作为载体,而int* &返回一个引用,是有这个值的载体。
我利用getRoot()函数(开头的代码)会返回一个指针的值(是一个地址值),但这个值无法被引用。这又涉及到一个知识点:
引用要明确指向一个具体的变量,而不能只是一个值。
所以出现这个报错。
将getRoot这样修改:
BinTreeNode<T>* &getRoot() { return root; }
即可返回root指针的引用,是一个具体的变量,于是便能成功在外部获取函数内建的树。
当然,在涉及树的实际开发过程中,并不推荐直接返回树根的引用,这样对于数据来说是不安全的。
最后再附图便于理解:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。