使用 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_ptr
或 std::unique_ptr
而不是原始指针
这两件事将为您解决很多问题
我尝试用 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_ptr
或std::unique_ptr
而不是原始指针
这两件事将为您解决很多问题