【发布时间】:2015-09-20 06:56:29
【问题描述】:
我正在编写一个类(一个 Huffman 编码器,如果您好奇的话),它需要包含一个专门的二叉树,而 STL 容器并不直接适用于该二叉树。用一些左/右指针定义一个TreeNode 结构并构建它是没有问题的。我的问题涉及节点本身的分配。
我认为如果我使用 STL 容器作为我的“分配器”而不是直接为每个节点调用 new 会非常好。这很有吸引力,因为它会使破坏变得微不足道:我不必在析构函数中遍历我的树来单独 delete 所有节点;我用作“分配器”的 STL 容器的库存析构函数会自动完成。
我对“分配器”的第一选择是std::vector<TreeNode>。但这根本不起作用,因为当然随着向量的增长,它必须重新分配自己,这会使我的所有指针无效。
所以我目前正在做的是坚持std::vector 的想法并放弃指针;我曾经有一个指针的每个地方都有一个整数,而不是在我的向量中保存一个索引。
也就是说,在我的父类中,我有类似的成员
std::vector<TreeNode> _heap; // all nodes in tree
int _root; // index into _heap
然后要分配一个新节点,我会这样做:
TreeNode newnode(/*whatever*/);
nodei = _heap.size();
_heap.push_back(newnode);
// now do something with nodei
事实上,这一切都很好,除了:使用索引而不是指针是一个简单的麻烦。我通常在任何地方都将指向节点引用为*nodep,我必须改用_heap[nodei]。 (但是,它再次起作用;这不是问题。)
我的问题是:
- 是否有一个 STL 容器类保证其元素以后不会移动,这样指向它们的指针将在容器的生命周期内保持有效?
- 指向 STL 容器中的元素的指针是个好主意吗?
- 对这类事情(即指向容器化堆中的元素)使用迭代器或引用而不是指针会更好吗?
- 是否有更好的方法来实现具有简单(即隐式)销毁语义的本地堆分配器?
我对其他想法持开放态度,尽管我应该警告你我相当保守。我想坚持在“基线”C++ 中工作的东西,即我会回避只在 C++11 或其他东西中使用的东西。而且我特别担心 sigc 和 boost 等包的开销和复杂性,所以我也不太可能想要使用它们的特殊容器或分配器之一。
【问题讨论】:
-
std::list应该适用于这种情况。 -
虽然它是 C++11(或 boost),但像
std::unique_ptr这样的智能指针会为您提供自动销毁。将节点存储在std::vector<std::unique_ptr<TreeNode>>中。如果 C++11 绝对不适合你,你当然可以实现自己的unique_ptr版本。
标签: c++ pointers memory-management stl heap-memory