为啥节点不能链接在一起?

Posted

技术标签:

【中文标题】为啥节点不能链接在一起?【英文标题】:Why can't the Nodes be linked together?为什么节点不能链接在一起? 【发布时间】:2009-10-12 04:41:28 【问题描述】:

编辑:是否可以不使用new? (不要动态分配内存)

我认为 push 是错误的,但我不知道在哪里、如何以及为什么。这是代码:

struct Node 
    string fileName;
    Node *link;
;
int size(Node *&flist) 
    int count = 0;
    Node *tempPtr = flist;
    while (tempPtr != 0) 
        count += 1;
        tempPtr->link = (tempPtr->link)->link;
    
    return count;

Node* push(Node *&flist, string name) 
    Node temp;
    Node *tempPtr = &temp;
    temp.fileName = name;
    temp.link = flist;
    cout << tempPtr->fileName << endl;
    cout << (tempPtr->link)->fileName << endl;
    return tempPtr;

int main( int argc, char *argv[] ) 
        Node aNode;
    Node *flist = &aNode;
    flist->fileName = "a";
    flist->link = NULL;
    push(flist, "b");
    int s = size(flist);
    cout << "size: " << s << endl;

输出是

b
a
size: 0

谢谢。

【问题讨论】:

我认为您缺少来自main 的一两行代码。 具体来说,没有提到文件“b”,也没有使用 push() 函数。 【参考方案1】:

在您的size() 函数中,您正在修改循环中的列表。您不想修改tempPtr-&gt;link,而只是在迭代时更改tempPtr。更改 tempPtr 不会永久修改任何内容。您还应该避免在此处通过引用传递flist,因为无需修改它。所以:

int size(Node *flist) 
    int count = 0;
    Node *tempPtr = flist;
    while (tempPtr != 0) 
        count += 1;
        tempPtr = tempPtr->link;
    
    return count;

至于push(),最大的问题是您将新节点分配为局部变量,这意味着它将在堆栈上并在函数返回时被销毁。要创建一个更永久的节点,您需要使用new 运算符在堆上分配它。同样,flist 的 '&' 是不必要的:

Node* push(Node *flist, string name) 
    Node *tempPtr = new Node;
    tempPtr->fileName = name;
    tempPtr->link = flist;
    cout << tempPtr->fileName << endl;
    cout << tempPtr->link->fileName << endl;
    return tempPtr;

请注意,new 的对应项是 delete。由于新节点是在堆上分配的,它们不会被自动销毁,所以当你完成列表时,你需要手动delete它们。您的目标是为每个new 分配一个delete,因此如果您使用new 5 个节点,您的代码在清理时应该delete 5 个节点。如果您不这样做,您的程序将运行良好,但会发生少量内存泄漏。

(实际上,当它退出时,所有分配的内存都会自动释放。但是通常分配内存而不释放它是一个坏习惯,所以你应该假装这种自动清理没有发生。)

【讨论】:

大小函数不应该有签名int size(const Node *flist);,因为它当然不应该修改列表中的任何内容。 Node 不应该也有构造函数吗... 我们不要压倒他。构造函数是一大罐蠕虫......! 为什么最好避免通过引用传递 flist?如果我需要修改它怎么办?那么 Node *&flist 至关重要? @derrdji:参数应根据函数的需要传递。作为一般规则,您的函数应该定义明确并且应该表现出预期的行为。返回堆栈大小的函数不会修改堆栈;因此堆栈参数不应通过引用传递给该函数。另一方面,像 push/pop 这样的函数应该修改堆栈,并且需要通过引用传递堆栈参数。【参考方案2】:

嗯,你的 size() 函数有点矫枉过正。你可以试试

int size(Node *flist) 
    int count = 0;

    Node *tempPtr = flist;
    while (tempPtr) 
        count += 1;
        tempPtr=tempPtr->link;
    

    return count;

我从 while 语句中删除了一个无关的退出条件,该条件阻止计算只有一个元素的列表的长度。

它在您的版本中返回 0 的原因是您的 while 语句:

while ((tempPtr != 0) &&(tempPtr ->link != 0)) 
        count += 1;
        tempPtr->link = (tempPtr->link)->link;
    

从不执行,因为您的一个节点的 .link 值为 null (0)。试试我上面提供的修改版本。

哦,将来,您可能希望将这类帖子标记为“家庭作业”。你会得到更好的回应。

【讨论】:

【参考方案3】:

您需要使用new。否则变量temppush 函数结束时被销毁。稍后,如果您尝试访问该指针指向的内容,它将消失。

【讨论】:

以上是关于为啥节点不能链接在一起?的主要内容,如果未能解决你的问题,请参考以下文章

为啥不能再在 Chrome 中移动 DOM 节点?

为啥 bootstrap-sass 不能与 Rails 一起使用?

Python:为啥 if-else 一行语句在 else 中不能与 continue 一起使用?

为啥 Laravel 中间件 CORS 不能与 Vue.js 一起使用

为啥链表几乎总是与单独的链接一起使用?

为啥我们不能在决策树中随机启动根节点?