考虑以下用于简单二叉树DFS遍历的c ++代码:
#include <iostream>
#include <vector>
using namespace std;
int print_vector(vector<char> *vec){
for (auto &it: *vec)
cout<<it;
cout<<'\n';
return 0;
}
int btree_dfs_traversal(int max_depth, int cur_depth, vector<char> position){
if (cur_depth>max_depth)
return 0;
print_vector(&position);
vector<char>left = position;
vector<char>right = position;
left.push_back('l');
right.push_back('r');
return btree_dfs_traversal(max_depth, cur_depth+1, left)+btree_dfs_traversal(max_depth, cur_depth+1, right);
}
int main(int argc, const char * argv[]) {
vector<char> pos;
btree_dfs_traversal(4, 0, pos);
return 0;
}
该函数(最小示例)访问二叉树,并打印&#34;位置&#34;它访问的每个节点。与标准DFS的唯一区别在于(这部分有所不同),大多数实现使用迭代来访问两个节点,而我的return
语句返回总和两次访问。
我希望程序从左边的语句中递归,即输出以l
,ll
,lll
开始,......实际上在我的系统(OSX)中它是像这样,ideone也有这个输出。
然而,在某些朋友中&#39;系统,输出是不同的。递归从右语句开始,即r
,rr
...不幸的是,我目前没有关于其编译器信息的确切信息。
我的问题是:两个递归的和是未定义的行为,这样不同的编译器可以产生不同的结果吗?或者,从右边开始是错的?
答案 0 :(得分:2)
“问题”是在f(1) + f(2)
中未指定哪个函数调用首先出现。不同的编译器将选择不同的顺序,顺序可以取决于任何数量的不相关因素。来自C ++参考:
评估顺序
几乎所有C ++运算符的操作数的评估顺序(包括函数调用表达式中函数参数的评估顺序以及任何表达式中子表达式的评估顺序)都未指定。编译器可以按任何顺序计算操作数,并且可以在再次计算相同表达式时选择另一个顺序。 这条规则有例外,如下所述。
除了下面提到的,C ++中没有从左到右或从右到左评估的概念。这不应与运算符的从左到右和从右到左的关联性混淆:表达式f1()+ f2()+ f3()被解析为(f1()+ f2())+ f3( )由于operator +的从左到右的关联性,但是对f3的函数调用可以在运行时的第一个,最后一个或f1()或f2()之间进行评估。
有关例外和更多信息,请参阅http://en.cppreference.com/w/cpp/language/eval_order。