【问题标题】:Inconsistent double pointer (linked list)双指针不一致(链表)
【发布时间】:2015-03-12 11:57:31
【问题描述】:

我正在开发一款游戏,它使用游戏中实体的链表。我发现我认为是某种错误。请注意,我正在使用 C 进行编码。但是在遇到 C 指针问题之后,我正在考虑尝试 C++ 技术。

在我的调试测试中,两个射弹相撞,将它们炸毁。基本上情况是这样的:

从实体的移动功能开始: 1) 射弹实体移动 2) 遍历所有在这个新位置检查碰撞的实体 3) 如果发生碰撞,在这种情况下是在弹丸之间,将两者都移除

我将实体的双指针传递给发生冲突的函数。该实体可能会被删除,但我仍然需要使用它来将实体推进到列表中的下一个实体(在 while 循环中)。如果这没有意义,它被视为这样:

    ENTITY *node;

    while (node)
    {
        ...

        entity_do_collision (&node); // <-- node may be removed in this function

        //Debug
        if (node == global_node)
        {
        }
        else
            node = global_node;

        node = node->next; // <-- pass a double pointer above so this works here
    }

所以,我已经多次运行代码,并没有看到任何非法操作。让我感动的部分是有时双指针会起作用,有时不会。我使用全局实体指针(始终有效)进行测试,以在我的实体移动函数中进行比较,以测试被删除的节点是否与实体删除函数中设置的内容相匹配。

这个描述有点抽象,如果我需要更多解释,请告诉我。

【问题讨论】:

    标签: c list pointers linked-list


    【解决方案1】:

    有无数种解决方案可以解决或不解决您的确切问题。

    以下是一些开始的想法:

    1. 不要在碰撞时从容器中删除对象,而是将它们标记为“死亡”。碰撞检测完成后,在单独的通道中清理“死”体。
    2. 在碰撞时将它们标记为死亡,但根本不删除。只需为未来的实体重复使用标记的节点即可。
    3. 对 (2) 的改进:对您的容器进行排序,因此“死”实体走到尾部并标记容器的大小,因为它只包含“活”实体
    4. (1)、(2)、(3) 的改进:实现某种“垃圾收集”,因此“死”实体将被清理,比如说每秒一次或一帧一次或达到内存阈值时。

    等等

    旁注:除非你真的,真的 别无选择,你明白你在做什么。默认使用数组,只有在你认为合理的情况下才使用其他东西。

    更多信息:

    【讨论】:

    • Bjarne Stroustrup。 C++ 编程语言(第 4 版)。 2013. 国际标准书号:978-0-321-56384-2。第 31.6 章。建议。第 924 页:'[2] 使用矢量作为默认容器'
    • 谢谢 Drop 这些都是很好的建议。我是一个相当新的程序员(2-3 年的业余爱好者),并且对 C 和“旧方式”感到满意。我想要一个编程良好的项目,但我只是认为如果我小心的话,我可以使用旧技术。但是,学习更可靠和更有效的“新方法”可能是值得的。
    • 您对为什么双指针可能无法可靠地返回正确地址有任何答案吗?还是没有足够的信息来确定?
    【解决方案2】:

    原码:

    ENTITY *node;
    
        while (node)
        {
            ...
    
            entity_do_collision (&node); // <-- node may be removed in this function
            node = node->next;
            /* the function can have changed node's value
            ** but on the next iteration ( on the **value** of node->next)
            ** the original node->next will not be affected!
            */
        }
    

    使用指针指向指针的示例代码:

    ENTITY **pp;
    for (pp = &global_node; *pp; pp = &(*pp)->next)
        {
            ...
    
            entity_do_collision (pp); // <-- *pp  (= node) may be removed in this function
    
            ...
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-11-15
      • 2011-03-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-12-13
      • 1970-01-01
      相关资源
      最近更新 更多