【问题标题】:temporary pointer point to a using vector address指向使用向量地址的临时指针
【发布时间】:2013-04-18 12:59:08
【问题描述】:

我有一个关于将字符串 s 解析为二叉树的问题。

struct TreeNode {
string val;         // The data in this node.
TreeNode *left;   // Pointer to the left subtree.
TreeNode *right;  // Pointer to the right subtree.
};

string s="((OR (AND pass (NOT reject)) (AND (NOT pass) reject)))";

我做了一些笔画并消除了“(”和“)”并将所有单独的部分保留在矢量后分割中, aftersplit 有(底部)OR AND 通过不拒绝并且不通过拒绝(返回)

vector<string> aftersplit;
vector<TreeNode> parsetree;
while (!aftersplit.empty())//do the parsing 
{

     TreeNode *temp=new TreeNode;

    temp->val=aftersplit.back();
    temp->left=NULL;
    temp->right=NULL;        
    aftersplit.pop_back();
    if(temp->val=="AND"||temp->val=="OR"||temp->val=="=>"||temp->val=="<=>"){
        TreeNode *leftnode = new TreeNode; 

        leftnode=&parsetree.back();
        parsetree.pop_back();
        temp->left=leftnode;
        TreeNode *rightnode = new TreeNode; 

        rightnode=&parsetree.back();
        parsetree.pop_back();
        temp->right=rightnode;
        parsetree.push_back(temp); //can not put the temp into parsetree 
    }
    else if(temp->val=="NOT")
    {
        TreeNode *leftnode = new TreeNode; 

        leftnode=&parsetree.back();
        parsetree.pop_back();
        temp->left=leftnode;
        parsetree.push_back(temp);        
    }
    else {            
        parsetree.push_back(temp);
    }

}

我从右到左处理字符串s

但是,当我在运算符为“OR”时运行“TreeNode leftnode”时;左节点被分配了一个地址,该地址被第一个“与”的左孩子“pass”使用,也就是说,“与”指向他的左孩子地址0x00007fff6d8da7e0,新的临时左节点正在分配地址0x00007fff6d8da7e0 太 在那之后 在此之前,树是这样的

    (AND)            
       / \        
      /   \       
   pass  (NOT)         
          /          
      reject  

在leftnode被分配“pass”的地址后,它会喜欢

                (AND)            
                 /    \        
                /      \       
              (AND)    (NOT)         
              /    \     /     
             /      \   /          
          (AND) (NOT) reject
         /    \        
        /      \       
     (AND)    (NOT)  

等等,都指向自己,我知道指针可能有问题,但我想不通。 请帮帮我

【问题讨论】:

    标签: c++ parsing pointers binary-tree


    【解决方案1】:
    if(temp.val=="AND"||temp.val=="OR"||temp.val=="=>"||temp.val=="<=>"){
        TreeNode leftnode;  //appear a bug here
        leftnode=parsetree.back();
        parsetree.pop_back();
        temp.left=&leftnode;
        TreeNode rightnode;
        rightnode=parsetree.back();
        parsetree.pop_back();
        temp.right=&rightnode;
        parsetree.push_back(temp);  
    }
    

    您的变量leftnoderightnode 的生命周期有限。由于它们是在您的if 范围内声明的,因此一旦您离开那里,它们就会被销毁。意味着他们的地址变得无效!因此,每次 temp.left 和 temp.right 的内容都会指向一些垃圾数据。

    这实际上就是为什么您可以看到多次找到相同地址的原因:由于前一个对象已被销毁,它被用于存储您需要的新数据。但这并不是您想要的,因为您想保留您创建的所有对象。

    最简单的方法是动态创建您需要的TreeNodes(并相应地修改其余代码):

    TreeNode *leftnode = new TreeNode;
    TreeNode *rightnode = new TreeNode;
    

    这样,即使在退出 if 之后,它们仍将保持有效。 但是,您以后一定不要忘记delete他们。

    【讨论】:

    • 我使用 TreeNode *leftnode = new TreeNode;树节点 *rightnode = 新树节点;在if and之外,还是得不到我想要的,能不能写的具体点,拜托~~~~
    • 这也适用于您的最顶层节点:TreeNode temp;。由于它是在您的 while 循环范围内声明的,因此一旦您退出它,它将被销毁。你也应该修改这个。
    • 我也修改了temp,但还是一样,也许我没有删除treenode,我应该在哪里删除treenode temp,leftnode和rightnode?​​span>
    • 其实我刚刚看到你的代码:你没有纠正主要问题!你写道:TreeNode leftnode=*new TreeNode();。您仍将结果存储在 TreeNode 中,该结果仍将在您的 if 末尾被销毁。您需要使用指向TreeNodeTreeNode* 的指针,并使用其中包含的地址。
    • 如果你使用TreeNode*,你的对象本身不会在作用域结束时被销毁,并且它的地址可以安全地使用(我所说的地址是指你的变量的内容。如在:TreeNode *leftnode = new TreeNode; temp.left = leftnode;)。通过保留TreeNode,您只是在堆中创建了一个额外的对象,但也将它存储在堆栈中。如果您使用堆栈上的对象的地址,问题将无法解决。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-30
    • 1970-01-01
    • 2011-08-04
    • 2015-06-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多