指针的元素保存为乱码

时间:2015-10-14 15:31:13

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

我编写的代码试图解决传教士和食人族的问题,并已实施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) {};

的main.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);
}

2 个答案:

答案 0 :(得分: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。如果在我认为它的示例位置创建了这个对象,那么你所创建的所有节点的父节点现在都指向这个新节点。

他们目前正在做的事情不会起作用。我不太确定你应该如何改变它以获得正确的行为。

答案 1 :(得分:0)

由于我还不能对其他人的帖子发表评论,我将以自己的答案为基础,继续前面的回答。是的,以下功能:

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();

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

编辑:显然,原始海报通过他的编辑打败了我。