实现树形结构最安全的方法是什么?
What is the safest way to implement a tree structure?
我想在程序中创建一个树形结构。现在我有类似于下面的内容:
class tree_node
{
public:
tree_node (tree_node* parent) : parent_(parent)
{
parent_.add_child(this);
}
private:
std::vector<tree_node*> children_;
tree_node* parent_;
}
我对这个设计的主要关注是tree_node
类可以删除它的任何子类和父类。我想改变设计,不允许这种情况发生。所以:
- 我能以某种方式改变设计使用引用而不是指针吗?(引用向量不起作用)。
- 如果我使用引用,我如何处理根节点的特殊情况(没有父节点)?
- 我可以禁止
tree_node
班删除孩子/家长吗?
一种安全的解决方案是将子指针存储为boost::shared_ptr,并将父指针存储为原始指针。然后根节点将其父节点设置为null
。
:
- 我能以某种方式改变设计使用引用而不是指针吗?(引用向量不起作用)。
在这种情况下必须使用指针。引用根本不起作用。
- 我可以禁止通过tree_node类删除子节点/父节点吗?
在设计树时,最常识性的所有权模型是节点拥有其子节点的所有权,而不是相反。
你是在说你想禁止一个类对它自己做一些事情。这怎么说得通呢?如果你不想让你的类删除它自己的子类,那就不要这样做。
编辑:回答标题中而不是文本中提出的问题:最安全的方法是不要重新实现树。使用标准库关联容器或可能的boost BGL。
您可以在容器中使用引用包装器类(如果需要,可以使用boost::optional
为父引用保存这样的包装器),但我不确定这是对您的潜在问题的解决方案。tree_node
类不做任何内存管理,所以没有特别的删除风险。
std::map
或其他关联容器之一,并避免编码一堆bug吗?显然,树的公共API不应该提供对节点类的直接访问(查看map
及其对迭代器的使用),所以只要树正确地管理内存,您对指针管理的担忧应该是最小的,因为您完全控制了节点的所有管理。
你的类不做任何内存管理,因此它不会删除任何其他节点。如果你想确保任何使用tree_node类的人不会删除任何父类或子类,你需要把它们放到一个纯虚拟基类中(它们是私有的),并让tree_node继承它。使用tree_node的用户将被迫使用您提供的方法。
同样,如果你不想太担心指针,可以使用智能指针(参见boost::shared_ptr)
我可以理解为什么不能允许子节点删除父节点,但我不明白为什么要禁止删除子节点。这是树中最基本的操作之一。
- 为不同配置设置MSVC_RUNTIME_LIBRARY的正确方法是什么
- 在C++中,将大的无符号浮点数四舍五入为整数的最佳方法是什么
- 实现无开销push_back的最佳方法是什么
- C++从另一个类访问公共静态向量的正确方法是什么
- 在 c++ 中拥有一组结构的正确方法是什么?
- 通过JNI传递数据数组的最快方法是什么
- 用常见虚拟函数实现的任意组合来实现派生类的正确方法是什么
- 使用不同的CRT将新的C++代码与旧的(二进制)组件隔离开来的最佳方法是什么
- 当无法使用模板和宏时,生成类型变体C++代码的最简单方法是什么?
- 在另一个类视图中添加最多2个图表的正确方法是什么
- 在C++中样板"冷/never_inline"错误处理技术的最佳方法是什么?
- 在 c++ 中对类中的 c 字符串动态数组进行排序的最佳方法是什么?
- 在C++中包含原型文件的正确方法是什么?
- 在 OpenCV C++ 中估计基本矩阵之前对相应点进行归一化的正确方法是什么?
- 在PostgreSQL中根据它们的ID选择大量行的最快方法是什么?
- 在OSX上使用CMake将Adobe的XMP工具包构建为共享库的最简单方法是什么?
- 将一系列整数放入类的最佳方法是什么?
- 从长整整转换为uint64_t的推荐方法是什么?
- 将此布尔值传递给此函数的最有效方法是什么?
- 通过比较C++中的行在 txt 文件中搜索的最简单方法是什么?