指针错误

问题描述:

我一直在为大型项目开发简单的二叉搜索树。我理解二叉搜索树的概念,并且在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); 
} 
} 

奖金问题:当树::爬网需要树&父的说法,而不是树父的运行良好。但是,如果没有&但它会失败。任何人都可以解释为什么这样吗?

你必须在堆上分配树(S)。

Tree node = Tree(value); 

在这里你正在堆栈上分配一棵树。这个变量的地址将在超出范围后处理。为了给它分配在堆中,只要使用new运算符:

Tree *node = new Tree(value); 

然后将其指定为父母的孩子:

parent.nodeChild2 = node; 

关于树::抓取错误,它是基于相同的错误。您继续在堆栈中分配树,因此,一旦它超出了作用域的调用,就会删除(ing)nodeChild1和nodeChild2。您应该通过使用指针或始终使用引用来管理这些类型的结构,以便在函数结束时不调用树的析构函数。因此:

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

这应该这样做。请记住,做同样的树:: findValue,你应该使用这个签名是功能:

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

谢谢你的这个作品,但是现在当调用Tree :: crawl时会发生同样的事情,程序编译就会崩溃。你能想到一个理由吗? – jozefg 2012-02-17 17:48:54

+0

如果你没有发布Tree :: crawl代码,我不能帮你:D – mfontanini 2012-02-17 17:52:52

+0

哦,真的吗?抱歉!我将张贴。 – jozefg 2012-02-17 17:57:22

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

而且,你的析构函数调用它的两个孩子delete,那么想必你应该在堆上分配的Tree实例来解决您的问题:Tree* node = new Tree(value);

+0

+1为'new' /'delete'对称。 – David 2012-02-17 17:44:51

+0

谢谢,你会认为考虑到我写了析构函数,我会发现错误,但是啊。 – jozefg 2012-02-17 17:55:38

Tree node = Tree(value); 

node有它在声明的程序块的范围将退出后自动deleled。出Tree::placeValue。当你得到指针时(parent.nodeChild2 = &node;),它会在退出后指向任何东西,并试图解引用它会导致未定义的行为。像这样动态创建它:

Tree * node = new Tree(value);