指针错误

时间:2012-02-17 17:34:28

标签: c++ pointers data-structures binary-tree

我一直在为一个更大的项目开发一个简单的二叉搜索树。我理解二叉搜索树的概念,并且只是在C ++中实现语法的麻烦。我故意不使用boost的树容器。我的树代码如下。

  struct Tree{
int nodeValue;
Tree *nodeChild1;
Tree *nodeChild2;
Tree(int userProvidedValue){
    nodeValue = userProvidedValue;
    nodeChild1 = NULL;
    nodeChild2 = NULL;
}
static void placeValue(Tree &parent, int value);
static Tree findValue(Tree parent, int value);
static void crawl(Tree parent);
~Tree(){

    delete nodeChild1;
    delete nodeChild2;
}
};

 void Tree::placeValue(Tree &parent, int value){
Tree node = Tree(value);
cout<<"made node"<<endl;
if(value>parent.nodeValue){
    cout<<"eval node child 2"<<endl;
    if(parent.nodeChild2 ==NULL){
        cout<<"reaching this";
        parent.nodeChild2 = &node;
    }
    else{
        placeValue(*parent.nodeChild2, value);
    }
}
if(value<=parent.nodeValue){
    cout<<"eval node child 1"<<endl;
    if(!parent.nodeChild1){
                cout<<"assigning"<<endl;
                parent.nodeChild1 = &node;
    }
            else{
                        placeValue(*parent.nodeChild1, value);
            }
        }
}

但是每当我用Tree parent = Tree(5)构造一个树然后用Tree::placeValue(parent, 4)添加另一个节点时,它编译得很好但会弹出一条消息告诉我exe已经崩溃了。

任何人都可以帮助我了解这次崩溃的来源吗?提前谢谢。

爬网树的代码如下所示:

void Tree::crawl(Tree parent){
cout<<parent.nodeValue<<endl;
if(NULL!=parent.nodeChild1){
    crawl(*parent.nodeChild1);
}
if(NULL!=parent.nodeChild2){
    crawl(*parent.nodeChild2);
}
}

奖金问题:当Tree :: crawl采用Tree&amp; parent的参数而不是Tree parent时,它运行正常。但没有&amp;但它失败了。任何人都可以解释为什么会这样吗?

3 个答案:

答案 0 :(得分:3)

您在堆栈中分配包含新值的Tree()实例,即Tree node = Tree(value);。当函数调用返回时,该实例被销毁,因此当您稍后尝试访问它时,程序崩溃。

此外,您的析构函数会对其子项调用delete,因此您可能应该在堆上分配Tree实例来解决您的问题:Tree* node = new Tree(value);

答案 1 :(得分:3)

您必须在堆上分配树。

Tree node = Tree(value);

在这里,您将在堆栈上分配一个树。该变量的地址将在超出范围后处理。要在堆上分配它,只需使用new运算符:

Tree *node = new Tree(value);

然后将其指定为父级的子级:

parent.nodeChild2 = node;

关于Tree :: crawl错误,它基于相同的错误。你继续在堆栈上分配树,因此一旦它超出范围,它的析构函数被调用,删除(ing)nodeChild1和nodeChild2。您应该通过使用指针或始终使用引用来管理这些类型的结构,这样当函数结束时,不会调用Tree的析构函数。因此:

void Tree::crawl(const Tree &parent){
  cout<<parent.nodeValue<<endl;
  if(NULL!=parent.nodeChild1){
      crawl(*parent.nodeChild1);
  }
  if(NULL!=parent.nodeChild2){
      crawl(*parent.nodeChild2);
  }
}

这应该这样做。记得在Tree :: findValue上做同样的事情,你应该为这个函数使用这个签名:

static Tree findValue(const Tree &parent, int value);

答案 2 :(得分:0)

Tree node = Tree(value);

node具有声明它的程序块的范围。退出Tree::placeValue后将自动删除它。当你获得指针(parent.nodeChild2 = &node;)时,它将在退出后指向任何内容并尝试取消引用它将导致未定义的行为。像这样动态创建它:

Tree * node = new Tree(value);