“指向指针的”小例子:忽然豁然开朗~
2728 点击·0 回帖
![]() | ![]() | |
![]() | 之前没有碰到过这类情况,也不知道实际工程中有什么奥妙,先来一个小的测试例子看一下运行结果: int a = 1; int b = 2; int *tmp = &a; int *p = tmp;// 第二种情况:int *;p = tmp;(此既是指向指针的) p = &b; *p = 5; 1、测试此时的a, b , *tmp, *p分别是什么: a = 1, b = 5, *tmp = 1, *p = 5; 2、如果是上述第二种情况,即指向指针的,那么这些变量又该是什么值呢?答案是: a = 1, b = 5, *tmp = 5, *p = 5; 这是因为指向指针的,不仅改变了指针所指的对象,也改变了指针本身。 下面以Essential C++ P177的代码举例: 该代码是为了删除一个二叉树中等于某个值的节点: 1 void BTnode::remove_value( const int; val, BTnode *; prev ) //二叉有序树中删除节点值_val == val的节点 2 { 3 if ( val < _val ) //往左子树遍历查找 4 { 5 if ( !_lchild ) 6 { 7 return; //不在此二叉树中 8 } 9 else _lchild->remove_value( val, _lchild ); 10 } 11 else 12 if ( val > _val ) // 往右子树遍历查找 13 { 14 if ( !_rchild ) 15 { 16 return; //不在此二叉树中 17 } 18 else _rchild->remove_value( val, _rchild ); 19 } 20 else 21 { //哈哈!~找到了~就是你啦!! 22 if ( _rchild ) //看看这个要被删除的节点是否有右孩子 23 { //果然有~~有点小麻烦了~~哎 24 prev = _rchild; 25 if ( _lchild ) //要删除的节点还有左孩子~得想办法把左孩子弄到右子树下面去,这样才能删除我这个节点 26 { 27 if ( !prev->_lchild ) //看看右子树是否有一堆左孩子 28 { 29 prev->_lchild = _lchild; 30 } 31 else BTnode::lchild_lead(_lchild, prev->_lchild);//遍历到右子树最左节点 32 } 33 } 34 else prev = _lchild; 35 delete this; //不用怕删除了本节点以后,我的孩子们连不到我的父辈节点们~~一句prev = _rchild解决了一切~~ 36 } 37 } 上面代码中红色部分是最关键的地方,比如下面这棵树: ![]() 其中的null是没有节点(我这样加个null是为了让6看起来是右孩子)。 在这个图里,我要删除5节点。若函数中参数是指针,而不是指向指针的。那么上述程序,就会造成删除了5节点以后,二叉树断成两部分。(prev = _rchild;这里我们只把prev重新改变为_rchild的值,而并没有改变5这个地址所指向的值,但我们程序中这一句就要让5的地址也改变) 而如果是指向指针的,prev = _rchild;这一句就会把5这个地址赋值为6的地址,这样删除5(即delete this;)之后就不会造成二叉树的断链问题。 Essential C++ P177是这么描述的: 为什么我们将prev以一个reference to pointer来传递呢?难道用单纯的pointer传递还不够吗?不,不够!以pointer来传递,我们能够更改的是该pointer所指之物,而不是pointer本身。为了该表pointer本身,我们必须再加一层间接性。如果将prev声明为reference to pointer,我们不但可以改变pointer本身,也可以改变由此pointer指向的对象。 | |
![]() | ![]() |