stackoverflow和C / C ++都是新手。我正在实现一个二叉树,并有一个简单的问题。可以说我有以下内容:
struct Node {
int data;
Node* right_child;
Node* left_child;
};
void addNode(Node* tree, int new_data){
if(tree == NULL){
Node* new_tree = new Node;
new_tree->data = new_data;
new_tree->right_child = NULL;
new_tree->left_child = NULL;
tree = new_tree;
}
}
int main(){
Node* tree = new Node;
tree = NULL;
addNode(tree, 3);
cout << tree->data << endl; //CRASH
}
非常简单吧。它会崩溃,因为即使从addNode返回后,树仍然是NULL。我试图理解的是为什么一旦调用addNode就不会更新它。当然,指针的副本被使用和更新,但它不应该仍然保持相同的地址吗?因此,仍然更新原始内存地址并返回。或者由于某种原因新指针指向不同的位置?我对发生的事感到困惑。任何帮助都会很棒。
另外,我刚刚在网站上写了这个代码 - 抱歉,如果没有什么错误,实际上没有运行它。
感谢。
答案 0 :(得分:4)
有一些问题,
首先,你有一个指针addNode
的本地副本,你没有取消引用它来对它指向的东西采取行动,而是直接作用于本地指针本身。在函数内部创建的new
ed Node
将永远丢失。
您可以通过引用传递指针来解决该问题。这不需要对您的代码进行任何其他修改:
void addNode(Node*& tree, int new_data)
其次,如您所述,您正在main
中取消引用NULL指针。这只是未定义的行为(UB)。可能发生的事情之一是崩溃。但代码可以只是静默运行而不会崩溃。重要的是它是UB并且不能依赖程序。
注1 :如果要初始化Node
以使数据成员初始化为零,请使用值初始化:
Node* tree = new Node();
注意2 :使用原始new
指针时要非常小心。您的代码中已经有一个 两个资源泄漏。更好地使用最合适的智能指针类型。
答案 1 :(得分:1)
由于您将指针传递给addNode
中的树void addNode(Node* tree, int new_data)
声明
tree = new_tree;
只是本地的,你不会改变传递指针所指向的内容,因为树是指针的副本。
与
比较void foo(int n) { n = 1; } // local, n is a copy
void foo(int* n) { *n = 1; } // change the original variabel
为了改变你需要传递指针地址的树点
void addNode(Node** tree, int new_data)
{
...
*tree = new Node;
...
}
答案 2 :(得分:-1)
如果要保持更改反映在main函数中(对于指针或非指针变量),安全方式是通过引用传递,因为引用变量只能初始化一次
即:
void addNode(Node*& tree, int new_data)
{
Node* tree_1;
tree = &tree_1 //this can't be done
}
void addNode(Node** tree, int new_data)
{
Node* tree_1;
tree = &tree_1 //this can be done
}
所以最安全的方法是通过引用传递,我的意思是void addNode(Node*& tree, int new_data)