2017-04-04 93 views
1

考慮以下C++代碼用於一個簡單的二進制樹DFS遍歷:不同遞歸輸出

#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; 
} 

的功能(一個最小的例子)訪問一個二叉樹,並打印各節點的「位置」它訪問。與標準DFS的唯一區別是(這部分有所不同),大多數實現使用迭代訪問這兩個節點,而我的return語句返回兩個訪問的

我希望該計劃從左邊聲明遞歸,即輸出開頭llllll,......的確在我的系統(OSX)就是這個樣子,和ideone有這種輸出了。

但是,在一些朋友的系統中,輸出是不同的。遞歸從右邊的聲明開始,即r,rr ......不幸的是,我目前沒有他們編譯器信息的確切信息。

我的問題是:總和的兩個遞歸是一個未定義的行爲,使不同的編譯器可以產生不同的結果?或者,從正確的開始是錯誤的?

+4

未指定首先計算算術表達式的兩邊中的哪一個。您可能想了解更多關於[評估順序和排序](http://en.cppreference.com/w/cpp/language/eval_order)。 –

+0

* sum *應該是相同的,但是程序中並沒有顯示它。 – molbdnilo

+0

@Someprogrammerdude我看到,在這種情況下,應避免使用總和 –

回答

3

「問題」是在中沒有指定哪個函數調用最先出現。不同的編譯器會選擇不同的順序,順序可以取決於任何數量的不相關的因素。從C++參考:

評價

幾乎所有的C++運算符(包括函數參數評價的一個函數調用表達的順序和評價的順序的操作數的評價的順序的順序任何表達式中的子表達式)都是未指定的。編譯器可以按任何順序評估操作數,並且可以在再次評估同一個表達式時選擇另一個順序。 這條規則有一些例外情況,這些例外如下。

除非在下面註明,否則在C++中沒有從左到右或從右到左的評估概念。這不應與運算符的從左到右和從右到左的關聯性相混淆:表達式f1()+ f2()+ f3()被解析爲(f1()+ f2())+ f3( )由於operator +的從左到右的關聯性,但可以在運行時首先,最後或在f1()或f2()之間評估對f3的函數調用。

查看http://en.cppreference.com/w/cpp/language/eval_order查看例外情況和更多信息。

+0

感謝您的詳細解釋 –