【发布时间】:2021-08-20 00:15:41
【问题描述】:
所以我有一个简单的 C++ 代码 sn-p,它应该将一个节点插入到二叉搜索树中。如果值被成功插入,则返回 true,如果值已经在树中,则返回 false。
struct Node {
int data;
Node* parent = nullptr;
Node* left = nullptr;
Node* right = nullptr;
};
bool insert(Node& root, int data) {
if (data > (root.data)) {
if ((root.right) == nullptr) {
Node newNode = {data, &root};
root.right = &newNode;
return true;
} else {
return insert(*root.right, data);
}
}
else if (data < (root.data)) {
if ((root.left) == nullptr) {
Node newNode = {data, &root};
root.left = &newNode;
return true;
} else {
return insert(*root.left, data);
}
}
else {
return false; // if both values are equal
}
}
在测试我的功能时,我发现了一些奇怪的东西。当我不打印函数的返回值时,它给出了正确答案(20):
Node root = {50};
insert(root, 20);
cout << (root.left->data) << endl;
然而,当我做打印返回值时,它给出了不正确的结果(0):
Node root = {50};
cout << insert(root, 20) << endl;
cout << (root.left->data) << endl;
我无法理解为什么会发生这种情况,但我最好的选择是因为一些奇怪的内存问题,也许没有为结构分配新内存?我来自 Python,内存管理是自动处理的,所以我仍然习惯这样的情况。
【问题讨论】:
-
Node newNode = {data, &root};创建一个局部变量,当它超出范围时被销毁。保留指向该变量的指针是未定义的行为。 -
不同的输出取决于我是否打印返回值 这可能意味着某种类型的未定义行为。编译器是否发出任何警告?编辑:@RetiredNinja 找到了 UB
-
奇怪的是,它没有产生警告或错误,至少在这种设置下没有:godbolt.org/z/fr857M1j9
-
我无法理解为什么会发生这种情况 -- C++ 并没有按照你认为的方式工作。这:
Node newNode = {data, &root}; root.right = &newNode;不会创建某种对newNode的永久引用,其中一些垃圾收集器看到它仍在使用中,因此不理会它。您需要重写您的代码,以便它在某种意义上使用动态内存分配实际创建节点。目前,在代码中的任何地方都没有发布过new或delete,也没有使用任何智能指针。 -
但是是的,这是您使用动态分配的情况。
std::unique_ptr非常适合这种情况。这是一个关于使用智能指针的精彩演示:youtube.com/watch?v=JfmTagWcqoE 如果你想不必要地折磨自己,你可以使用new。
标签: c++ memory-management binary-search-tree nodes