2017-10-13 61 views
0

我正在實現一個簡單的Tree類來在解析器中使用,我需要遍歷解析樹的結構並逐步構建它。爲什麼我的deque元素四處移動?

這是類的精簡版,演示了這個問題(在this repl.it session可執行文件):

template <typename T> 
class Tree { 
    T val; 
    std::deque<Tree<T>> children; 

public: 
    Tree() {} 
    Tree(T value) : val(value) {} 
    Tree(T value, std::deque<Tree<T>> children) : val(value), children(children) {} 

    std::deque<Tree<T>> getChildren() { return this->children; } 

    void appendChild(T value) { 
    this->children.push_back(value); 
    // this->children.emplace_back(value); 
    std::cout << "Appended child to node with value " << this->val << ".\n"; 
    printChildren(); 
    } 

    void printChildren() { 
    std::cout << "children for " << this << "(" << this->val << ")" 
       << ": { "; 
    for (auto &child : this->children) { 
     std::cout << &child << "(" << child.val << ") "; 
    } 
    std::cout << "}\n"; 
    } 
}; 

對於每個節點,孩子們都存儲在一個std::deque所以孩子們可以加入到任何一端。在測試我的課程時,我發現我不能依賴增量樹建立的結構,而是使用初始化程序列表一次性完成。

下面是一些代碼行使類,並顯示發生的事情:

std::cout << "Constructing Tree\n\n"; 
Tree<int> t(1); 
t.appendChild(2); 
t.getChildren()[0].appendChild(3); 

std::cout << "\n\nPrinting tree from main\n\n"; 
t.printChildren(); 
t.getChildren()[0].printChildren(); 

這有以下的輸出:

Constructing Tree 

Appended child to node with value 1. 
children for 0x7ffe9fd41820(1): { 0xb69080(2) } 
Appended child to node with value 2. 
children for 0xb694a0(2): { 0xb696b0(3) } 


Printing tree from main 

children for 0x7ffe9fd41820(1): { 0xb69080(2) } 
children for 0xb698c0(2): { } 

正如你所看到的,節點與價值2地址每次打印出來都不一樣。當它首先附加到1節點時,它的地址爲0xb69080。它得到自己的孩子後,它的地址爲0xb694a0。然後,當從main函數訪問它時,它的地址爲0xb698c0

此外,它似乎當它被移動它不知何故失去了它的孩子。最後一行應顯示2節點有一個值爲3的單個子節點。

這是怎麼回事?

回答

4

我想你的問題是在這裏

std::deque<Tree<T>> getChildren() { return this->children; } 

getChildren()回報複製兒童

std::deque<Tree<T>> & getChildren() { return this->children; } 
// .................^ 

嘗試參考返回內部children,如果你想使用的返回值進行修改。

我的意思是:如果getChildren()返回children一個副本,其中

t.getChildren()[0].appendChild(3); 
您提供超值 3孩子追加到一個由 getChildren()返回的 children副本的第一個元素

此副本未保存,因此它是一個臨時值,在丟失3子項後立即銷燬。

+0

謝謝!我正在思考我需要實現移動/複製構造函數的思路,但通過引用返回是我想要做的。 – Kevin

相關問題