【问题标题】:Pointer's elements saved as gibberish指针的元素保存为乱码
【发布时间】:2015-10-14 15:31:12
【问题描述】:

我编写了试图解决传教士和食人者问题的代码,并实现了Node 以将信息保存在Node::arrNode::parent 中。这些,当由函数bfs 返回时,将给出最短路径中的状态。

bfs 返回时,它有正确的parents 编号。然而,当我在 Visual Studio 调试器中检查Node last 时,我注意到它的parents.arr 包含垃圾,即arr[0]=-858993460。但是Node last 有正确的arr(问题的最终状态{0,0,1,3,3,0})。这些信息是如何丢失的?

node.h

#pragma once
#include <array>
class Node {
public:
    std::array<int, 6> arr;
    Node *parent;
    Node(std::array<int, 6> arr, Node *parent = NULL);
    Node();
};

node.cpp

#include "Node.h"

Node::Node(std::array<int, 6> arr, Node *parent) : arr(arr), parent(parent) {};
Node::Node(): parent(NULL) {};

ma​​in.cpp

void applyMoves(queue<Node> &q, Node current_node, array<int, 3> moves) {
  array<int, 6> arr = current_node.arr;
    array<int, 3> left, right;
    // apply valid moves to arr
    // copy the arr to left and right and check if the move applied are valid
    // if valid and no duplicates in the queue do proceed to the next lines below
    Node n = Node(arr, &current_node);
    q.push(n);

}

Node bfs(queue<Node> &q, array<array<int, 3>, 5> moves) {
    while (!q.empty()) {
        Node current = q.front();
        q.pop();

        if (achievedGoal(current.arr) == 1) {
            return current;
        }
        for (const auto& move : moves) {
            applyMoves(q, current, move);
        }
    }
    Node n;
    return n;
}

int main() {
    array<int, 6> init_state{ 3,3,1,0,0,0 };
    array<array<int, 3>, 5> moves{ { {1,0,1}, {0,1,1}, {1,1,1}, {2,0,1}, {0,2,1} } };
    Node n = Node(init_state);
    queue<Node> q;
    q.push(n);
    Node last = bfs(q, moves);
}

【问题讨论】:

  • 您的默认Node 构造函数未初始化parent(可能与您遇到的问题无关)。
  • 另外,applyMoves 采用 current_node 的值,然后你使用它的地址。
  • @crashmstr 我将applyMoves 更改为接收Node &amp;current_node 并像这样调用applyMoves(q, current, move); 但是,当我检查Node last 时,似乎有一个永无止境的“级别” parent 指向 parent

标签: c++ pointers c++11 c++14


【解决方案1】:

我认为问题出在

void applyMoves(queue<Node> &q, Node current_node, array<int, 3> moves) {
  array<int, 6> arr = current_node.arr;
    array<int, 3> left, right;
    // apply valid moves to arr
    // copy the arr to left and right and check if the move applied are valid
    // if valid and no duplicates in the queue do line 31 and 32
    Node n = Node(arr, &current_node);
    q.push(n);

}

这里current_node 是一个副本,您正在存储它的地址。当函数结束时,副本被销毁,现在你有一个悬空指针。您应该可以通过引用 current_node 来修复它。

编辑:

你在

中也有同样的行为
Node bfs(queue<Node> &q, array<array<int, 3>, 5> moves) {
    while (!q.empty()) {
        Node current = q.front();
        q.pop();

        if (achievedGoal(current.arr) == 1) {
            return current;
        }
        for (const auto& move : moves) {
            applyMoves(q, current, move);
        }
    }
    Node n;
    return n;
}

在这里,您创建 current 这是一个本地自动对象,您将队列的前端复制到其中,然后将 pop() 前端从队列中取出。因此,当您将此节点用于父节点时,一切都很好,直到您移动到 ​​while 循环的下一次迭代。一旦你这样做了,current 就会被销毁,这意味着指向它的所有东西现在都悬空了。然后循环开始备份并创建一个新的current。如果这个对象是在我认为的示例位置创建的,那么您创建的所有节点现在都有它们的父节点指向这个新节点。

他们目前这样做的方式是行不通的。我不太确定您应该如何更改它以获得正确的行为。

【讨论】:

  • 我将applyMoves 更改为接收Node &amp;current_node 并像这样调用applyMoves(q, current, move); 但是,当我检查Node last 时,父母指向的位置似乎有一个无止境的“级别”给父母。
  • @user2348707 我已经更新了我的答案。不太确定如何解决算法接缝损坏的问题。
  • 感谢您的回答!现在我对这个问题有了更好的理解。我很快在 python 中进行了原型设计,并在 C++ 上尝试了我的手,即使代码几乎相同,它们的行为也非常不同。我将不得不尝试另一种方法来获得正确的行为。
  • @user2348707 没问题。很高兴为您提供帮助。
【解决方案2】:

由于我(还)不能评论其他人的帖子,我将在之前的答案的基础上用我自己的答案。是的,如下函数:

void applyMoves(queue<Node> &q, Node current_node, array<int, 3> moves) {
  array<int, 6> arr = current_node.arr;
    array<int, 3> left, right;
    // apply valid moves to arr
    // copy the arr to left and right and check if the move applied are valid
    // if valid and no duplicates in the queue do line 31 and 32
    Node n = Node(arr, &current_node);
    q.push(n);

}

需要通过引用获取 current_node,否则,您会将地址存储到局部变量中,该地址将在执行超出函数范围后被销毁。

但是,不仅如此,还有这里:

    Node current = q.front();
    q.pop();

您正在复制队列中的第一个元素,并将其保存到局部变量中,当您将其传递给上述函数时(即使它是通过引用完成的),您仍然会遇到同样的问题,因为您正在存储局部变量的地址(不同函数的局部变量,但仍然 - 同样的问题)。而且,根据发布的逻辑,我不清楚正确的解决方案是什么,但至少你有“为什么?”回答。

编辑:显然最初的发帖人用他的编辑打败了我。

【讨论】:

  • 谢谢!回答“为什么”总比没有好。我至少学到了一些东西。
猜你喜欢
  • 2013-08-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-02-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-04-08
相关资源
最近更新 更多