在 main() 中打印双向链表的行为与使用外部函数打印它的行为不同
Printing Doubly-Linked-List in main() behaves different than printing it with an outside function
如果我在下面编写 while 循环(取消注释以编译它)打印此双向链表中的节点,我会看到“all_gods”列表变为空(因为“all_gods = all_gods->下一步();")
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++ 中的函数参数(引用除外)是所传递内容的副本。
当您使用 loop
函数打印列表时,all_gods
的值被复制到参数 p
。然后,参数 p
用于打印列表而不对变量 all_gods
.
产生任何影响
变量 all_gods
指向列表的第一项。如果你用
修改它
all_gods = all_gods->next();
那么您实际上失去了对当前项目的访问权。
当循环迭代直到 all_gods
变为 nullptr
时,您只剩下一个:nullptr
,这意味着 一个空列表.
该程序完全按照您的指示执行。
为了避免这种效果,您需要使用 all_gods
的 copy 来遍历列表,如 @JosephLarson 在 中所示。
迭代列表成员的正确方法如下:
for (Link *ptr = all_gods; ptr != nullptr; ptr = ptr->next) {
...
}
您的代码破坏了指向列表头部的指针。您需要使用新指针进行迭代。
如果我在下面编写 while 循环(取消注释以编译它)打印此双向链表中的节点,我会看到“all_gods”列表变为空(因为“all_gods = all_gods->下一步();")
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++ 中的函数参数(引用除外)是所传递内容的副本。
当您使用 loop
函数打印列表时,all_gods
的值被复制到参数 p
。然后,参数 p
用于打印列表而不对变量 all_gods
.
变量 all_gods
指向列表的第一项。如果你用
all_gods = all_gods->next();
那么您实际上失去了对当前项目的访问权。
当循环迭代直到 all_gods
变为 nullptr
时,您只剩下一个:nullptr
,这意味着 一个空列表.
该程序完全按照您的指示执行。
为了避免这种效果,您需要使用 all_gods
的 copy 来遍历列表,如 @JosephLarson 在
迭代列表成员的正确方法如下:
for (Link *ptr = all_gods; ptr != nullptr; ptr = ptr->next) {
...
}
您的代码破坏了指向列表头部的指针。您需要使用新指针进行迭代。