当我为树编写一些代码时犯了一个错误时,我遇到了以下奇怪的情况。我已经对这个示例进行了很多精简,因此它只是一个线性树。
基本上,在 main() 函数中,我想将一个节点附加到我的树上,但我没有将其附加到“tree.root”,而是仅将其附加到“root”。然而,令我惊讶的是,它不仅编译得很好,而且我能够调用节点上的方法。仅当我尝试访问“value”成员变量时才出错。
我想我的主要问题是,为什么编译器没有捕获这个错误?
std::shared_ptr<Node> root = tree.AddLeaf(12, root);
因为 RHS 上的“root”是一个完全未声明的变量。另外,出于好奇,如果编译器允许它们通过,循环定义是否有实际的用例?这是其余的代码:
#include <iostream>
#include <memory>
struct Node
{
int value;
std::shared_ptr<Node> child;
Node(int value)
: value {value}, child {nullptr} {}
int SubtreeDepth()
{
int current_depth = 1;
if(child != nullptr) return current_depth + child->SubtreeDepth();
return current_depth;
}
};
struct Tree
{
std::shared_ptr<Node> root;
std::shared_ptr<Node> AddLeaf(int value, std::shared_ptr<Node>& ptr)
{
if(ptr == nullptr)
{
ptr = std::move(std::make_shared<Node>(value));
return ptr;
}
else
{
std::shared_ptr<Node> newLeaf = std::make_shared<Node>(value);
ptr->child = std::move(newLeaf);
return ptr->child;
}
}
};
int main(int argc, char * argv[])
{
Tree tree;
std::shared_ptr<Node> root = tree.AddLeaf(12, root);
std::shared_ptr<Node> child = tree.AddLeaf(16, root);
std::cout << "root->SubtreeDepth() = " << root->SubtreeDepth() << std::endl;
std::cout << "child->SubtreeDepth() = " << child->SubtreeDepth() << std::endl;
return 0;
}
Output:
root->SubtreeDepth() = 2
child->SubtreeDepth() = 1
这是 C++ 中定义的一个不幸的副作用,声明和定义是作为单独的步骤完成的。因为变量是declared首先,它们可以在自己的初始化中使用:
std::shared_ptr<Node> root = tree.AddLeaf(12, root);
^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^
Declaration of the variable Initialization clause of variable
一旦声明了变量,就可以在初始化中使用它来实现其自身的完整定义。
这将导致未定义的行为 https://en.wikipedia.org/wiki/Undefined_behavior in AddLeaf
如果使用第二个参数的数据,因为变量未初始化。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)