【问题标题】:Printing Doubly-Linked-List in main() behaves different than printing it with an outside function在 main() 中打印双向链表与使用外部函数打印它的行为不同
【发布时间】:2021-07-08 15:33:41
【问题描述】:

如果我在下面编写打印此双向链表中节点的 while 循环(取消注释以编译它),我看到“all_gods”列表变为空(因为“all_gods = all_gods->next(); ")

all_gods:
 0x560c837b1f30 Odin
 0x560c837b1ef0 Ares
 0x560c837b1eb0 Zeus

0x560c837b1f30 Odin
0x560c837b1ef0 Ares
0x560c837b1eb0 Zeus
all_gods:

但如果我在 main() 之外的函数中移动相同的 while 循环,那么 all_gods 将保持不变。

all_gods:
 0x55aedf48ef30 Odin
 0x55aedf48eef0 Ares
 0x55aedf48eeb0 Zeus

0x55aedf48ef30 Odin
0x55aedf48eef0 Ares
0x55aedf48eeb0 Zeus
all_gods:
 0x55aedf48ef30 Odin
 0x55aedf48eef0 Ares
 0x55aedf48eeb0 Zeus

为什么会这样?谢谢!

#include <iostream>
#include <string>
using namespace std;

class Link
{
public:
    Link(const string n, Link *p = nullptr, Link *s = nullptr)
        : name{n}, prev{p}, succ{s}
    {
    }
    Link *insert(Link *n); // insert n before this object

    Link *next() const { return succ; }
    Link *previous() const { return prev; }
    ~Link()
    {
        delete succ;
    }

    string name;

private:
    Link *prev;
    Link *succ;
};
Link *Link::insert(Link *n) // insert n before this object; return n
{
    if (n == nullptr)
        return this;
    if (this == nullptr)
        return n;
    n->succ = this;     // this object comes after n
    if (prev)           // if prev of this (object) is not zero
        prev->succ = n; 
    n->prev = prev;     // this object’s predecessor becomes n’s predecessor
    prev = n;           // n becomes this object’s predecessor
    return n;           // returns n (the new element) which is before the top node
}
void print_all(Link *p)
{
    while (p)
    {
        cout << " " << p << " " << p->name;
        if (p = p->next()) // moved to the next node
            cout << "\n";
    }
}
void loop(Link *p)
{
    while (p)
    {
        cout << p << ' ' << p->name << '\n';
        p = p->next();
    }
}
int main()
{
    Link *all_gods = new Link{"Zeus"}; 
    all_gods = all_gods->insert(new Link{"Ares"});
    all_gods = all_gods->insert(new Link{"Odin"});

    cout << "all_gods:\n";
    print_all(all_gods);
    cout << "\n\n";

    // while (all_gods)
    // {
    //     cout << all_gods << ' ' << all_gods->name << '\n';
    //     all_gods = all_gods->next();
    // }
    loop(all_gods);

    cout << "all_gods:\n";
    print_all(all_gods);
    cout << "\n";

    delete all_gods;
}

【问题讨论】:

    标签: c++ doubly-linked-list


    【解决方案1】:

    遍历列表成员的正确方法如下:

    for (Link *ptr = all_gods; ptr != nullptr; ptr = ptr->next) {
        ...
    }
    

    您的代码会破坏指向列表头部的指针。您需要使用新的指针进行迭代。

    【讨论】:

    • 谢谢约瑟夫!您的回答有助于解决我遇到的另一个问题(如何根据匹配提取节点,然后将搜索移动到下一个节点,而不破坏指针)。
    【解决方案2】:

    C++ 中的函数参数(引用除外)是所传递内容的副本。

    当您使用loop 函数打印列表时,all_gods 的值被复制到参数p。然后,参数p 用于打印列表,而不会对变量all_gods 产生任何影响。

    【讨论】:

    • 你是对的,迈克!我将函数更改为“loop(Link *&p)”,现在我得到了相同的结果。我认为指针有一些我不明白的地方:)
    【解决方案3】:

    变量all_gods 指向列表的第一项。如果你修改它

    all_gods = all_gods-&gt;next();

    那么你实际上失去了对当前项目的访问权限。

    当循环迭代直到 all_gods 变为 nullptr 时,你只剩下:nullptr,这意味着 一个空列表

    该程序完全按照您的指示行事。

    为避免这种影响,您需要使用all_gods副本 来遍历列表,正如@JosephLarson 在this answer 中显示的那样。

    【讨论】:

      猜你喜欢
      • 2019-05-01
      • 2021-11-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-15
      • 1970-01-01
      • 2021-07-24
      相关资源
      最近更新 更多