为什么我的元素在移动

Why are my deque elements moving around?

本文关键字:移动 元素 我的 为什么      更新时间:2023-10-16

我正在实现一个简单的Tree类,以便在解析器中使用,在解析器中我需要遍历解析树的结构并逐步构建它。

这是演示该问题的类的精简版本(可在此repl.it会话中执行):

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 Treenn";
Tree<int> t(1);
t.appendChild(2);
t.getChildren()[0].appendChild(3);
std::cout << "nnPrinting tree from mainnn";
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的子节点。

这是怎么回事?

我想你的问题就在这里

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子项。