c++ - 使用默认复制构造函数会破坏 C++ 中的树
问题描述
例如:
#include <iostream>
#include <vector>
#include <string>
using namespace std;
struct TreeNode {
vector<TreeNode> children;
string name;
};
int main() {
TreeNode leafNode;
leafNode.name="c";
TreeNode middleNode;
middleNode.name="b";
middleNode.children.push_back(leafNode);
TreeNode rootNode;
rootNode.name="a";
rootNode.children.push_back(middleNode);
rootNode=rootNode.children[0];
cout <<rootNode.name <<endl;
}
输出c
,在 CLANG 和 GCC 中。当然,我希望它输出b
. 这里发生了什么?
解决方案
正如其他人在评论中指出的那样,您真的应该尝试设置调试器并首先调试您的代码。这就是你在编程中学到很多东西的方式。
但是,如果您不习惯调试,您可能很难找到问题所在,因为有问题的代码是编译器生成的。
您是对的,复制构造函数或多或少会损坏您的数据。但这不是编译器的错。默认复制构造函数通过引用获取其参数,并且您将 的成员的引用传递rootNode
给 的复制构造函数rootNode
。所以实际上你是用它自己的一部分覆盖对象。
在分配或复制过程中或多或少发生了什么:
TreeNode(const TreeNode& other) {
children = other.children;
name = other.name;
}
因此,如果您传递rootNode.children[0]
给此操作,它将有效地简化为:
rootNode.children = rootNode.children[0].children; // copies the children of 'b' to 'a'
rootNode.name = rootNode.children[0].name; // children[0] now refers to the first
// of 'b's children, so name will be 'c' !!
一种可能的解决方法是首先使用以下方法创建真实副本:
rootNode = TreeNode{ rootNode.children[0] };
行为可能因编译器而异。在 VS2019 中,我在尝试您的示例时得到一个空输出。
推荐阅读
- c# - 从 C# 中的地图中删除时间戳
- javascript - 利用 Measurement Protocol 将 Google Analytics 连接到 CRM
- c - 如何将 char[] 写入结构?
- c++ - Valgrind 显示内存泄漏?可能与fftw有关?
- azure - 如何使用 Azure Az CLI 以编程方式创建使用 Autopilot 预配的 Azure CosmosDB
- git - Git 克隆到取自 URI 的目录
- mapbox-android - Firebase 模拟器 com.facebook.soloader.SoLoader$WrongAbiError
- unity3d - 如何混合多种纹理?
- c++ - C++ HTTP Client recv() 和写入文件问题
- python - 如何在 Kivy 上创建可滚动的浮动布局?