【问题标题】:Vector attributes on class instance in returned pointer attribute disappearing返回的指针属性中类实例上的向量属性消失
【发布时间】:2020-06-05 15:41:19
【问题描述】:

我正在实现一种树搜索,它需要能够从树中获取“最有希望的节点”,然后对该节点执行某些操作,以便为下一次迭代更新树的其余部分。

问题:对象指针Board* 的向量属性似乎在产生它们的函数的return 和在调用环境中保存它们的Board* 值之间变化。

我的输出:

>>g++ -std=c++17 -o tmp.out tests/test.cpp // <- require c++17 for other parts of the project
>>./tmp.out 
Best leaf by tree traversal has score: 8
Best leaf associated state has -1977735524 values in its attribute vector though! (Should be 4)

我的期望:

>>g++ -std=c++17 -o tmp.out tests/test.cpp // <- require c++17 for other parts of the project
>>./tmp.out 
Best leaf by tree traversal has score: 8
Best leaf associated state has 4 values in its attribute vector though! (Should be 4)
#include <iostream>
#include <vector>
#include <queue>

using namespace std;

class Board{
    vector<int> attribute;
    string name;
public:
    Board(){
        attribute = {1,2,3,4};
        name = "nonempty name";
    }
    Board getcopy(){
        return *this;
    }
    int AttrLen(){
        return attribute.size();
    }
};

class Node{
    Board* board;

    Node* parent;

    std::vector<Node*> children;

    int depth=0;

    int score=0;

    bool terminal=false;
public:
    Node(Node* _parent, Board* _board,int _depth){
        parent = _parent;
        board = _board;

        depth = _depth;

        // randomize score
        score = rand() % 10;

        if(depth<2){
            for(int _=0;_<2;_++){
                Board new_state = board -> getcopy();
                children.push_back(new Node(this,&new_state,depth+1));
            }
        } else {
            children = {};
            terminal=true;
        }
    }
    int getScore(){
        return score;
    }
    bool isTerminal(){
        return terminal;
    }
    Node* getBestChild(){
        if(!terminal){
            if(children[0] ->getScore() > children[1] -> getScore()){
                return children[0];
            } else {
                return children[1];
            }
        } else {
            return nullptr;
        }
    }
    Board* getStateptr(){
        return board;
    }

};

int main(){

    // make a board
    Board my_board = Board();

    // make a root node
    Node root = Node(nullptr, &my_board, 0);

    Node* best_child = root.getBestChild();
    while(!best_child -> isTerminal()){
        best_child = best_child -> getBestChild();
    }

    cout << "Best leaf by tree traversal has score: " << best_child -> getScore() << endl;
    cout << "Best leaf associated state has " << best_child -> getStateptr() ->AttrLen() << " values in its attribute vector though! (Should be 4)" << endl;

}

【问题讨论】:

  • 现在这段代码失败的原因与我的真实代码失败的原因相同。我最感兴趣的是为什么Board* 上的向量属性在返回和调用环境实例化之间改变大小。我试图做到这一点,以便打印输出显示我在说什么。
  • 当我编译并运行它时,我得到了一堵输出墙,但我不知道你认为它有什么问题。请在问题中包括输出和预期输出。请尽量减少代码,我想不是所有的代码都需要重现问题
  • 啊,是的,我想这很重要。我减少了打印输出并尝试使打印输出更具可读性,并添加到我的输出/预期输出中。
  • new_childNode*,为什么会打印&lt;node_hash1&gt;

标签: c++ pointers tree monte-carlo-tree-search


【解决方案1】:

不确定这是否是唯一的问题,但在这里

for(int _=0;_<2;_++){
    Board new_state = board -> getcopy();
    children.push_back(new Node(this,&new_state,depth+1));
}

您创建了一个 Board 的副本,它只存在于 for 循环中。它会在} 自动销毁。因此,您存储在节点中的指针是悬空的。指向早已不复存在的对象。

请注意,您的 getcopy 有点奇怪。您应该改用复制构造函数。通常,当您的类型通过原始指针管理资源时(不确定是否确实如此),那么您需要遵守 3/5 规则。在任何情况下,您都可以简单地通过编写Board new_state = *board; 来复制电路板(假设编译器生成的复制构造函数是正确的)。

【讨论】:

  • 我认为这是正确的轨道。关于尝试构建 C++ 树的另一篇文章指出了同样的问题。我想我必须回到绘图板上,要么尝试完全避免复制状态(无论如何我在实现中很少需要这样做),要么找到一种处理矢量属性的方法,使它们易于复制。 stackoverflow.com/questions/51111109/c-tree-data-structure
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-06-14
  • 2021-11-16
  • 2018-11-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多