繁体   English   中英

指针是如何工作的

[英]How do pointers work

这是一个简单的代码,我在问我的问题。

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。

for (int i = 2; i < 5; i++){
    Class next;
    next.key = 2;
    p->next = &next;
    p = p->next;
}

next对象的生命周期在每次迭代结束时结束。 由于您将此对象的地址分配给p->next ,因此当迭代结束时,此指针将保持悬空状态。 在下一次迭代中,当您尝试使用p ,您将调用未定义的行为。

你的逻辑似乎是正确的,但正如其他评论员所指出的那样,在循环中创建的变量是该循环的本地变量,因此一旦你离开循环就会过期。 你需要一个小修改。

替代解决方案:只需用以下内容替换您的第一个循环:

for (int i = 2; i < 5; i++){                    
    p->next = new Class;
    p->next->key = i;           
    p = p->next;
}

这将分配所需的内存并在每次迭代时创建一个新条目。

希望有所帮助!

问题是在这个循环中

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。

您应该动态分配每个节点或使用列表中的节点数组。

这是一个演示程序,展示了如何通过数组使用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

解释Chris的评论 - 访问其范围之外的变量是未定义的行为。 你的next变量的范围是for循环的一次迭代,一旦你达到了循环的结束} (我认为i++已经运行),编译器需要处理为next释放内存,然后重新初始化它下一次运行。 你的编译器似乎作出合理的决定,以保持next在同一块内存,并在每次迭代,这就是为什么你的内存访问是不扔分割故障(IE再次运行构造函数中,试图访问存储你的程序有没有被授予访问权限)。 您的编译器也可以在退出for循环后决定next解除分配,但似乎也没有这样做,这就是您能够访问其内存进行打印的原因。

长话短说,不要过于担心弄清楚你的程序为什么会这样做,而是使用kvorobiev所示的堆内存,这将持续到for循环范围的末尾。 作为良好的做法,您也应该在完成记忆后delete内存。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM