You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

TreeNode* root与TreeNode* &root作为函数参数的区别是什么?

TreeNode* root和TreeNode* &root作为函数形参的区别

这两种写法实际效果存在本质区别,绝对不能混用。

1. 传TreeNode* root的本质:值传递的指针

  • 函数接收到的是实参指针的拷贝副本,形参和实参是两个独立的指针变量,只是初始时指向同一块TreeNode内存。
  • 在函数内通过这个指针修改指向的TreeNode对象内容(比如修改root->val、给root->left/root->right赋值),因为操作的是同一块内存,外部的实参能感知到变化。
  • 但如果在函数内直接修改形参指针本身的指向(比如写root = new TreeNode()、root = nullptr),改动只作用在本地副本上,外部的实参指针不会有任何变化。

2. 传TreeNode* &root的本质:指针的引用传递

  • 形参是外部实参指针的别名,没有拷贝过程,形参和实参完全是同一个东西。
  • 除了能正常修改指向的TreeNode对象内容之外,在函数内修改指针本身的指向(给root重新赋值新地址、置空),改动会直接作用在外部的实参指针上,函数执行完外部能直接拿到改动后的指针值。

直观代码示例

#include <iostream>
using namespace std;

struct TreeNode {
    int val;
    TreeNode *left;
    TreeNode *right;
    TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
};

// 值传递指针
void func1(TreeNode* root) {
    root = new TreeNode(100); // 仅修改本地副本指针
}

// 引用传递指针
void func2(TreeNode* &root) {
    root = new TreeNode(200); // 直接修改外部实参指针
}

int main() {
    TreeNode* p = nullptr;
    func1(p);
    cout << "After func1, p is nullptr? " << (p == nullptr ? "Yes" : "No") << endl; 
    // 输出Yes,func1的改动没有影响外部p
    
    func2(p);
    cout << "After func2, p->val = " << p->val << endl; 
    // 输出200,func2直接改了外部p的指向
    return 0;
}

常见使用场景

  • 日常做二叉树遍历、查询、修改已有节点属性的操作时,用TreeNode* root就足够,不会有问题。
  • 当需要在函数内修改传入的指针本身的指向——比如写二叉树插入/删除节点逻辑、递归建树时需要给上层返回新创建的根地址、处理空节点要挂载新节点的场景,必须用TreeNode* &root,否则对指针本身的赋值无法传递到函数外,会出现逻辑错误。

最常见的踩坑场景:写二叉搜索树插入递归函数时用值传递指针,递归到空节点位置给root赋了新节点,运行完发现树里根本没插入新节点,本质就是值传递只改了副本指针,上层的左右孩子指针根本没被更新。

内容的提问来源于stack exchange,提问作者arpit jain

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 04:45:38