我偶然发现了一个有趣的案例,让我质疑我对if语句的了解。
我有用于插入二叉树的代码:
void insert(Node<T>* ¤tNode, const T& x)
{
if (currentNode == nullptr)
{
currentNode = new Node<T>(x);
}
if (x >= binTree<T>::root->data)
{
insert(currentNode->right, x);
}
else if (x < binTree<T>::root->data)
{
insert(currentNode->left, x);
}
}
我面临的问题是每当我调用此函数插入树时,它就会给我一个分段错误,在运行valgrind之后,它告诉我发生了堆栈溢出错误。我通过编写一个cout语句测试了第一个if块是否导致了问题,并且看到我的cout语句被无限次地执行了多次。
然而,在将第二个if块更改为一个统一的if语句之后:
if {}
else if {}
else if {}
代码运行完美,并没有停留在无限循环中。如何解释这种行为? if语句是否仅测试条件,如果为false则继续在块的其余部分进行?
答案 0 :(得分:4)
应该很明显。
如果没有else
,对insert
的每次调用总是至少再调用一次insert
,从而导致无限次调用。第二个if
始终执行,无论是哪种方式都调用insert
。
使用else
,如果insert
为空,则insert
可能无法调用currentNode
。
答案 1 :(得分:2)
由于这个答案迟到了,所以不希望得到这个答案,但是想要增加另一个观点。这里的问题是你在没有基本情况(等于堆栈溢出)的情况下(有意或无意)创建了一个递归函数。
保证以下陈述之一为真:
if (x >= binTree<T>::root->data)
{
insert(currentNode->right, x);
}
else if (x < binTree<T>::root->data) //could just as well have been only "else"
{
insert(currentNode->left, x);
}
通过实施您找到的解决方案以及@David Schwartz确认的解决方案,您实际上将if (currentNode == nullptr)
块转换为基本案例,从而解决了问题。