这是一个简单的代码,我在问我的问题。
struct Class{
public:
int key;
Class*next;
};
int main(){
Class c;
c.key = 1;
Class* p = &c;
for (int i = 2; i < 5; i++){
Class next;
next.key = i;
p->next = &next;
p = p->next;
}
p = &c;
for (int i = 1; i < 5; i++){
std::cout << p->key;
p = p->next;
}
}
我期待的输出:1234
输出我得到:1444
请你告诉我我的代码有什么问题,以及如何获得1234。
答案 0 :(得分:2)
for (int i = 2; i < 5; i++){
Class next;
next.key = 2;
p->next = &next;
p = p->next;
}
next
对象的生命周期在每次迭代结束时结束。由于您将此对象的地址分配给p->next
,因此当迭代结束时,此指针将保持悬空状态。在下一次迭代中,当您尝试使用p
时,您将调用未定义的行为。
答案 1 :(得分:1)
你的逻辑似乎是正确的,但正如其他评论员所指出的那样,在循环中创建的变量是该循环的本地变量,因此一旦你离开循环就会过期。你需要做一个小修改。
替代解决方案:只需用以下代码替换您的第一个循环:
for (int i = 2; i < 5; i++){
p->next = new Class;
p->next->key = i;
p = p->next;
}
这将分配所需的内存并在每次迭代时创建一个新条目。
希望有所帮助!
答案 2 :(得分:0)
问题是在这个循环中
for (int i = 2; i < 5; i++){
Class next;
next.key = 2;
p->next = &next;
p = p->next;
}
对于每次迭代,您使用相同的局部变量。因此,对于循环p->next
的第二次迭代,指向同一本地对象。
因此,您的porgram具有未定义的行为,因为退出循环后此本地对象不活动。通常情况下,可以覆盖局部变量占用的内存。
结果似乎是节点。一个是c
,它指向已经“死亡”的节点,而死亡节点next
指向自身,并保留存储在数据成员key
中的最后一个值为4. / p>
您应该动态分配每个节点或使用列表中的节点数组。
这是一个演示程序,展示了如何通过数组使用simialr方法。
#include <iostream>
struct Class
{
public:
int key;
Class *next;
};
int main()
{
const size_t N = 4;
Class c[N];
c[0].key = 1;
Class *p = &c[0];
for ( size_t i = 1; i < N; i++ )
{
c[i].key = i + 1;
p->next = &c[i];
p = p->next;
}
p = &c[0];
for ( int i = 0; i < N; i++ )
{
std::cout << p->key;
p = p->next;
}
std::cout << std::endl;
return 0;
}
输出
1234
答案 3 :(得分:0)
解释Chris的评论 - 访问其范围之外的变量是未定义的行为。你的next
变量的范围是for循环的一次迭代,一旦你达到了循环的结束}
(并且i++
已经运行了,我认为),这取决于编译器处理释放next
的内存,然后在下次运行时重新初始化它。您的编译器似乎正在做出合理的决定,将next
保留在同一块内存中,并在每次迭代时再次运行构造函数,这就是为什么您的内存访问不会引发分段错误(IE,尝试访问内存)程序未被授予访问权限)。退出next
循环后,您的编译器也可能决定取消分配for
,但似乎也没有这样做,这就是您可以访问其内存进行打印的原因。
长话短说,不要过于担心弄清楚你的程序为什么会这样做,而是使用kvorobiev所示的堆内存,这将持续到for循环范围的末尾。作为良好的做法,一旦你完成了记忆,你也应该delete
。