简体   繁体   English

使用 cout 从八叉树打印元素会改变内容吗?

[英]Printing an element from an octree with cout alters the content?

I tried creating an octree in c++. Seems to work fairly well, but when I print the content of the tree it returns an access violation error.我尝试在 c++ 中创建一个八叉树。似乎工作得很好,但是当我打印树的内容时,它返回访问冲突错误。 Running this in debug will print two different numbers, although the content should not have been changed.在调试中运行它会打印两个不同的数字,尽管内容应该没有改变。 Here is the printout:这是打印输出:

2
11
32762

From what digging I have done it seems like the cout statement ends up mutating the octree object. I don't see why this should happen.从我所做的挖掘来看,cout 语句似乎最终改变了八叉树 object。我不明白为什么会发生这种情况。 If my approach is faulty, then why does it work in the first.get statement?如果我的方法有问题,那么为什么它在 first.get 语句中起作用?

Here is my code:这是我的代码:

#include <iostream>
typedef unsigned int uint;

template <typename T>
class OcTree {
    struct Node {
        Node* parent;
        uint depth;

        Node* children[8];
        T* data;
        
        Node(Node* parent, uint depth, uint max_depth) : parent{parent}, depth{depth} {
            for (int i=0; i<8; i++) {
                children[i] = nullptr;
            }
            if (depth == max_depth) {
                data = new T[8];
                for (int i=0; i<8; i++) {
                    data[i] = T(); //Initialize data to default values
                }
            } else {
                data = nullptr;
            }
        }
        ~Node() {
            delete[] data;
        }
    };

    uint max_depth;
    Node root;

    static uint make_subindex_from_index(uint x, uint y, uint z, uint depth) {
        uint mask = 1 << depth;
        uint x_bit, y_bit, z_bit;
        x_bit = x & mask;
        y_bit = y & mask;
        z_bit = z & mask;
        return compose_subindex(x_bit, y_bit, z_bit);
    }
    static uint compose_subindex(uint x_bit, uint y_bit, uint z_bit) {
        uint out = 0;
        if (x_bit) out += 4;
        if (y_bit) out += 2;
        if (z_bit) out += 1;
        return out;
    }

public:
    OcTree(uint max_depth) : max_depth{max_depth}, root{Node(nullptr, 0, max_depth)} {}

    uint get_range() {
        return (uint)1 << max_depth;
    }

    void insert(uint x, uint y, uint z, T item) {
        Node* current_node = &root;
        uint subindex;
        for (uint d = 0; d < max_depth; d++) {
            subindex = make_subindex_from_index(x, y, z, d);
            if (current_node->children[subindex] == nullptr) { //If the next node doesn't exist yet
                Node new_node = Node(current_node, d+1, max_depth); //Make it
                current_node->children[subindex] = &new_node;
            }
            current_node = current_node->children[subindex];
        }
        subindex = make_subindex_from_index(x, y, z, max_depth);
        current_node->data[subindex] = item;
    }

    T get(uint x, uint y, uint z) {
        Node* current_node = &root;
        uint subindex;
        for (uint d = 0; d < max_depth; d++) {
            subindex = make_subindex_from_index(x, y, z, d);
            if (current_node->children[subindex] == nullptr) {
                std::cout << "Item does not exist!";
                throw -1;
            }
            current_node = current_node->children[subindex];
        }
        subindex = make_subindex_from_index(x, y, z, max_depth);
        return current_node->data[subindex];
    }
};
//Temporary for testing purposes
int main() {
    OcTree<int> test_tree = OcTree<int>(1);
    std::cout << test_tree.get_range() << "\n";
    test_tree.insert(0, 1, 2, 11);
    std::cout << test_tree.get(0, 1, 2) << "\n";
    std::cout << test_tree.get(0, 1, 2) << "\n";
}

The specific error is here具体错误在这里

           Node new_node = Node(current_node, d+1, max_depth); //Make it
            current_node->children[subindex] = &new_node;

'new_node' is a local variable and it will get destroyed once this function exits. 'new_node' 是一个局部变量,一旦 function 退出,它就会被销毁。 You cannot store its address, its meaningless.你不能存储它的地址,它没有意义。 UB. UB。

You need你需要

           Node *new_node = new Node(current_node, d+1, max_depth); //Make it
            current_node->children[subindex] = new_node;

Ie allocate it on the heap.即在堆上分配它。 Now you will have to deal with delete ing it once you are done with it.现在,一旦完成,您将不得不处理delete ing。

You would be so so much better off if you learned to use如果你学会使用,你会过得更好

  • std::vector for you arrays of things (like children) std::vector给你 arrays 的东西(比如孩子)
  • std::shared_ptr or std::unique_ptr instead of raw pointers std::shared_ptrstd::unique_ptr而不是原始指针

these 2 things will take care of a lot of issues for you这两件事会为你解决很多问题

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

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