这是我的Node类。
class Node
{
private:
public:
T data;
Node<T>* left;
Node<T>* right;
Node(T dat) : data(dat), left(NULL), right(NULL)
{}
};
这是我的插入函数,在我的Btree类中定义:
public:
Node<T>* root;
Btree() : root(NULL){}
void insert(T data, Node<T>* parent)
{
if( !parent )
{
parent = new Node<T>(data);
return;
}
else if(data < parent->data)
{
insert(data, parent->left);
}
else if(data > parent->data)
{
insert(data, parent->right);
}
}
};
这是我的主要功能:
int main()
{
Btree<int> tree;
tree.insert(5, tree.root);
cout << tree.root->data << endl;
tree.insert(6, tree.root);
cout << tree.root->right->data << endl;
}
当我跑步时,我得到一个段错误。
我认为这是因为指针变量parent是通过值传递的,所以当我创建一个由父指向的新节点时,一旦我退出插入函数,我就输了吗?这是否意味着我必须在这里使用双指针?
有人可以给我一个彻底的解释,说明内存中发生了什么,这使得这不能按计划进行。我的诊断是正确的还是有其他错误的?
当我将tree.root作为要插入的第二个参数传递时,我传递了一个Node *,我知道的很多。现在,即使它是按值传递的,它也不是我从调用main函数传递的地址。所以,当我说父(这是我从main传递的地址,tree.root)=新节点时,是否应该在堆上创建一个新的Node,在父地址处,也就是tree.root的地址?为什么通过价值掠过这个?
答案 0 :(得分:2)
在这种情况下传递值的问题是调用者看不到函数内部形式参数的所有赋值。因此,这个作业
if( !parent )
{
parent = new Node<T>(data); // <<== HERE
return;
}
对来电者的tree.root
没有影响:
tree.insert(5, tree.root);
更改函数中parent
指针的值,然后立即丢弃;树的root
仍为NULL
。
修复此问题的方法是将指针传递给指针,如下所示:
void insert(T data, Node<T>** parent) {
if( !*parent )
{
*parent = new Node<T>(data);
return;
}
else if(data < (*parent)->data)
{
insert(data, &((*parent)->left));
}
else if(data > (*parent)->data)
{
insert(data, &((*parent)->right));
}
}
答案 1 :(得分:2)
C ++按值传递,因此parent
是传入指针的副本。因此,分配给它没有持久的影响。解决此问题的最简单方法是更改方法的签名,以便接受对指针的引用。这将自动使编译器更新原始指针,同时避免更改程序的其余部分。
答案 2 :(得分:1)
dasblinkenlight 回答得最好。但是,有一个更简洁的解决方案:
获取指针的引用(称为指针引用):
void insert(T data, Node<T>*& parent)
{
if( !parent )
{
parent = new Node<T>(data);
return;
}
else if(data < parent->data)
{
insert(data, parent->left);
}
else if(data > parent->data)
{
insert(data, parent->right);
}
}
在此处查看更多信息: http://www.codeproject.com/Articles/4894/Pointer-to-Pointer-and-Reference-to-Pointer