C++ 中使用指针引用的必要性和例子

本文通过一个二叉查找树删除节点的例子,探讨了在C++中使用指针引用的必要性。错误地传递指针值导致删除操作失败,正确做法是传递指针引用或指针的指针。文中详细解释了为何传递指针副本无法修改原始指针,并提供了修改方法。

在用C++实现二叉查找树delete操作时出现了奇怪的行为,要被删除掉的节点并没有被删除,而是值变成了0,一番查找确认算法本身没问题,最后发现是向函数传递参数时出现的错误,函数应该接收的是指针引用或者指针的指针,但我的实现接收的是指针的值,先贴正确代码

class TreeNode
{
public:
	TreeNode(int v): val(v), left(NULL), right(NULL){}
	int val;
	TreeNode *left, *right;
};

bool Delete(TreeNode * &root)
{
	TreeNode *temp = NULL;
	if (!root->left)
	{
		temp = root;
		root = root->right;
		delete temp;
		temp = NULL;
	}
	else if (!root->right)
	{
		temp = root;
		root = root->left;
		delete temp;
		temp = NULL;
	}
	else
	{
		temp = root;
		TreeNode *cur = root->left;
		while (cur->right)
		{
			cur = cur->right;
		}
		cur->right = root->right;
		root = root->left;
		delete temp;
		temp = NULL;
	}

	return true;
}

bool deleteNode(TreeNode * &root, int x)
{
	if (!root) return false;
	if (root->val == x)
		return Delete(root);
	else if (root->val > x)
		deleteNode(root->left, x);
	else
		deleteNode(root->right, x);
}

这里使用的删除策略是,当被删除节点 p 的左子树和右子树均不为空时,令 p 的左子树成为 p 父节点的左(右)子树,p 的右子树成为 p 的前驱的右子树,删除 p。用户调用 deleteNode 函数,Delete 应是私有函数,被 deleteNode 调用。

原来错误版本代码与这个版本的唯一不同,就是两个函数的参数列表中都是 TreeNode *root,而不是指针引用。那么区别在哪?当我们把一根指针传递给一个函数,其实也是把指针拷贝了一份副本传递给了函数,与一般的函数传值并无不同,这样做当只是想修改指针指向的对象时并无不妥,但是当要改变指针本身的指向时就会出问题,函数内部做出的修改只是在副本上的修改,而原本的指针仍保留着原来的值。例如下面的例子,它的两次输出均为 “outside”:

void test(string *p)
{
	p = new string("inside");
}

int main()
{
	string ss = "outside";
	string *p = &ss;
	cout<< *p<< endl;
	test(p);
	cout<< *p<< endl;

	return 0;
}

若想得到想要的 “outside”,“inside” 输出,最简单的方法就是改成 void test(string * &p),这样内部代码无需改动就可实现功能。或者使用指针的指针,如下:

void test(string **p)
{
	*p = new string("inside");
}

int main()
{
	string ss = "outside";
	string *p = &ss;
	cout<< *p<< endl;
	test(&p);
	cout<< *p<< endl;

	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值