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

Printing an element from an octree with cout alters the content?

我尝试用 C++ 创建一个八叉树。似乎工作得很好,但是当我打印树的内容时,它 returns 出现访问冲突错误。 运行 这在调试中会打印两个不同的数字,尽管内容应该没有改变。这是打印输出:

2
11
32762

从我所做的挖掘来看,cout 语句似乎最终改变了八叉树对象。我不明白为什么会这样。如果我的方法有问题,那么为什么它在第一个 .get 语句中起作用?

这是我的代码:

#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";
}

具体错误在这里

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

'new_node' 是一个局部变量,一旦这个函数退出,它就会被销毁。你不能存储它的地址,它没有意义。 UB.

你需要

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

也就是在堆上分配。现在你将不得不处理 delete 一旦你完成它。

如果你学会使用,你会过得更好

  • std::vector 给你一堆东西(比如小孩)
  • std::shared_ptrstd::unique_ptr 而不是原始指针

这两件事将为您解决很多问题