关于指针做函数参数-》指针的值传递和引用传递
上图中,指针q在传入 setnull 函数时,将 q 赋给了 setnull 的一个临时拷贝!因此在 setnull 函数中 令 t = nullptr 时,并不会影响到主程序中的q。
从指针的地址也可以看出,setnull 函数中的临时指针和主程序中的指针并不是同一个指针!
如果想在函数中改变主程序中的指针值本身,可以使用指针的引用:
将函数设置为:
void setnull(TreeNode * & q) {
...
}
当关系理不清时,建议执行以下程序:
#include <iostream>
using namespace std;
struct TreeNode {
int val;
TreeNode *left;
TreeNode *right;
TreeNode() : val(0), left(nullptr), right(nullptr) {}
TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
};
void setnull(TreeNode * t) {
cout << "t : " << t << endl;
cout << "&t : " << &t << endl;
cout << "t->right : " << t -> right << endl;
cout << "&(t->right) : " << &(t -> right) << endl;
t -> right = nullptr;
}
int main(void) {
TreeNode * a = new TreeNode(1);
TreeNode * b = new TreeNode(2);
a -> right = b;
cout << "a : "<< a << endl;
cout << "&a : " << &a << endl;
cout << "b : " << b << endl;
cout << "&b : " << &b << endl;
cout << "a->right : " << a -> right << endl;
cout << "&(a->right) : " << &(a -> right) << endl;
setnull(a);
if (b) {
cout << "b is not nullptr" << endl;
}
return 0;
}
设置a、b两个树节点指针并分配对象,令a->right = b;
,需要注意的是,当调用setnull(a)
后,指针 a 和指针 t 不是同一个指针变量(从它们的地址 &a 和 &t 不同可以看出来),这是因为指针的形参是值传递,因此 指针 t 是指针 a 的一个拷贝。但是它们指向同一个 TreeNode 对象(从它们的值 a 和 t 相同可以看出来)。a->right 和 t->right 的值相同(从 a->right 和 t->right 的值相同可以看出来),即这两个指针指向同一个 TreeNode 对象。同时 a->right 和 t->right 是同一个指针变量(从 &(a->right) 和 &(t->right) 相同可以看出来)!这是因为 a 和 t 指向同一个对象,而 a->right 和 t->right 都是(该对象)的 right 指针变量。可以把 -> 换成 * 来理解,即 (*a).right 和 (*t).right 是同一个指针变量,这是显然的,因为 a 和 t 虽然是不同的指针,但是它们指向的对象(即 *a 和 *t)都是同一个对象。
最后,在 setnull 中令 t->right=nullptr
,主程序中的 b 不会被赋值为空指针,因为 t->right 即 (*t).right ,与 (*a).right 是同一个指针变量,而 (*a).right 和 b 并不是同一个指针变量(从 &(a->right) 和 &(b) 不同可以看出来),它们只是指向同一个 TreeNode 对象。
一图: