【问题标题】:c++ use of *& as parameter (Pointer fun, tertiary tree method)c++使用*&作为参数(指针乐趣,三叉树方法)
【发布时间】:2013-03-07 13:35:42
【问题描述】:

我正在尝试编写一种将键值对添加到三叉树的方法,但显然我做错了什么,因为每当我到达标记的代码时都会出现段错误

void Tree::add(int k, Node *&r)
{
    cout<<"add"<<endl;
    if(r==NULL){
        r = new Node(k);
        //check(heap area);
    }

开始问题代码

    else if(r->keyCount == 1){
        cout<<"adding second key";
        if(r->getKey() < k){
            Node * temp = new Node(r->getKey(),k,r->data[0],0);
            delete r;
            r = temp;
            r->keyCount++;
            cout<<"test"<<endl;
        }
        else
        {
            Node * temp = new Node(k,r->getKey(),0,r->data[0]);
            delete r;
            r = temp;
            r->keyCount++;
            cout<<"test"<<endl;
    }

结束代码

    }
    else if(k < r->getKey())
    {
        cout<<"left"<<endl;
        add(k,r->child[Node::L]);
    }
    else if(r->keyCount > 1 && k < r->getKey(1))
    {
        cout<<"middle"<<endl;
        add(k,r->child[Node::M]);
    }
    else if(r->keyCount > 1 && k > r->getKey(1))
    {
        cout<<"right"<<endl;
        add(k,r->child[Node::R]);
    }
    else
        r = new Node(k);
}

我要做的是,如果在这个特定节点中使用的 2 个密钥中只有 1 个,则将当前节点替换为在适当位置具有密钥的新节点(较小的 val在 key[0] 中,key[1] 中的 val 更大) 我该如何正确地做到这一点?

我的代码显然删除了旧节点的地址和指针,但没有正确地将指针重新分配给新节点。

编辑 更新的代码。输出如下:

% p4
Enter pairs consisting of an int and a double. I create a
ternary tree, keeping the data in order, by int. Finish entering
data by pressing ^d
2 2
add
Entering the pair: 2, 2
1 1
add
adding second key to current node
test
Entering the pair: 1, 1
-1 -1
add
left
add
Entering the pair: -1, -1
3 3
add
right
Segmentation Fault

编辑 2 如果您想查看所有代码,这里是一个包含整个项目的 zip 的链接:http://sdrv.ms/WSrLfv

编辑 3 更多错误数据 - 崩溃时 gdb 的输出

Program received signal SIGSEGV, Segmentation fault.
0x08051628 in getData (x=@0x8047554) at testTree.cc:26
26            x[k]=d;
Current language:  auto; currently c++

编辑 4 单步执行 gdb 到 segfault:

Breakpoint 1, Tree::add (this=0x8047554, k=3, r=@0x8047554) at tree.cc:58
58          cout<<"add"<<endl;
(gdb) n
add
61          if(r==NULL){
(gdb) n
65          else if(r->keyCount == 1){
(gdb) n
87          else if(k < r->getKey())
(gdb) n
92          else if(r->keyCount > 1 && k < r->getKey(1))
(gdb) n
97          else if(r->keyCount > 1 && k > r->getKey(1))
(gdb) n
99              cout<<"right"<<endl;
(gdb) n
right
100             add(k,r->child[Node::R]);
(gdb) n

Breakpoint 1, Tree::add (this=0x8047554, k=3, r=@0x806416c) at tree.cc:58
58          cout<<"add"<<endl;
(gdb) n
add
61          if(r==NULL){
(gdb) n
62              r = new Node(k);
(gdb) n
107     }
(gdb) n
107     }
(gdb) n
Tree::operator[] (this=0x8047554, index=3) at tree.cc:47
47          return *(locate(index,root)->data);
(gdb) n
48      }
(gdb) n

Program received signal SIGSEGV, Segmentation fault.
0x08051628 in getData (x=@0x8047554) at testTree.cc:26
26            x[k]=d;
(gdb)

【问题讨论】:

  • 哇,你可以在 C++ 中做 *& 吗?那是指针的引用还是引用的指针?我想我的大脑已经很痛了……
  • @Patashu 这是对指针的引用
  • 这就是 BEGIN CODE 和 END CODE 的用途。我解释了我正在尝试做什么,以及它显然在做什么。我正在尝试更改调用此方法的对象中指针的值,而不是它指向的地址处的值。
  • 究竟哪一行出现了段错误?
  • 如果您传递给add() 的指针不是不确定的,它应该可以工作。即,在任何代码运行之前确保它为 NULL。

标签: c++ oop pointers methods


【解决方案1】:

这应该可以工作。

响应您的编辑:我注意到您的输出中有一些有趣的东西:

-1 -1
add
left
add
Entering the pair: -1, -1

请注意它是如何说“左”的,然后由于递归调用而说“添加”。但是,在使程序崩溃的输入中,您看不到“添加”之后:

3 3
add
right
Segmentation Fault

如果您查看您的 Tree::locate 函数:

Node * Tree::locate(int k, Node *rt) const
{
if(rt==NULL)
    return rt;
if(k==rt->getKey())
    return rt;
if(rt->keyCount>1 && k==rt->getKey(1))
    return rt;
if(k < rt->getKey())
{
    return locate(k,rt->child[Node::L]);
}
else if(rt->keyCount>1 && k < rt->getKey(1))
{
    return locate(k,rt->child[Node::M]);
}
else if(rt->keyCount>1 && k<rt->getKey(1))
{
    return locate(k,rt->child[Node::R]);
}
else
    return NULL;
}

这一行:

else if(rt->keyCount>1 && k<rt->getKey(1))

与前一个条件相同,因此被完全跳过。

【讨论】:

  • 段错误似乎发生在右子节点的递归调用上,在最后一个 else if 语句中。
  • 好吧,我检查了一下,数组被声明为 Node *child[3];,所以它不是越界错误。此外,Node::R 确实引用了数字 2,并声明为 enum{L=0,M,R};
  • @Dazedy 事实上,我刚刚检查了你的代码。尽管如此,问题仍然存在,它在cout &lt;&lt; "add" 之前崩溃了,我怀疑add() 甚至被调用了,我认为它在此之前就崩溃了。
  • 同意。它发生在它打印“right”之后,并且在它可以打印“add”之前,所以它必须在 add(k,r->child[Node::R]); 内,很可能在参数中。
  • 会不会是导致这种情况的条件不正确? else if(r-&gt;keyCount &gt; 1 &amp;&amp; k &gt; r-&gt;getKey(1)),这样添加 Node::R 就没有意义(甚至崩溃)?只是一个想法,我还在检查你的代码。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-03-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多