Я столкнулся со следующей странностью, когда сделал ошибку при написании кода для деревьев. Я много раз сократил этот пример, так что это только линейное дерево.
По сути, в функции main() я хотел присоединить Node к своему дереву, но вместо того, чтобы прикреплять его к "tree.root", я прикрепил его просто к "root". Однако, к моему удивлению, все это не только прекрасно скомпилировалось, но и я мог вызывать методы на узлах. Он только допустил ошибку, когда я попытался получить доступ к переменной-члену "value".
Наверное, мой главный вопрос: почему компилятор не уловил эту ошибку?
std::shared_ptr<Node> root = tree.AddLeaf(12, root);
Так как "корень" в RHS является полной необъявленной переменной. Кроме того, из любопытства, если компилятор пропускает их, есть ли у циклических определений реальный вариант использования? Вот остальная часть кода:
#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;
}
Выход:
root->SubtreeDepth() = 2
child->SubtreeDepth() = 1