I'm writing a class (a Huffman encoder, if you're curious) that needs to contain a specialized binary tree for which an STL container wasn't directly appropriate. And it's no problem to define a TreeNode structure with some left/right pointers and build the thing. The questions I have concern the allocation of the nodes themselves.
I thought it would be really nice if I used an STL container as my "allocator", rather than directly calling new for each node. This was attractive because it would make destruction trivial: I wouldn't have to walk my tree in the destructor to individually delete all the nodes; the stock destructor for the STL container I'd used as my "allocator" would do it automatically.
My first choice of an "allocator" was std::vector<TreeNode>. But this didn't work at all, because of course as the vector grows, it has to reallocate itself and that invalidates all my pointers.
So what I'm doing for the moment is clinging to the std::vector idea and abandoning the pointers; every place I used to have a pointer I have an integer holding an index into my vector instead.
That is, in my parent class I have members like
std::vector<TreeNode> _heap; // all nodes in tree
int _root; // index into _heap
And then to allocate a new node I do something like this:
TreeNode newnode(/*whatever*/);
nodei = _heap.size();
_heap.push_back(newnode);
// now do something with nodei
And in fact this is all working just fine, except: working with indices instead of pointers is a plain nuisance. Everywhere I'd normally reference a pointed-to node as *nodep I have to use _heap[nodei] instead. (But, again, it works; that's not the problem.)
My questions are:
- Is there an STL container class that is guaranteed not to have its elements move around later, such that pointers to them will remain valid for the container's lifetime?
- Are pointers to elements within STL containers ever a good idea?
- Would it be better to use iterators or references instead of pointers for this sort of thing (that is, to point to the elements in the containerized heap)?
- Is there a better way to implement a local heap allocator, with easy (i.e. implicit) destruction semantics?
I'm open to other ideas, although I should warn you that I'm pretty conservative. I'd like to stick with something that works in "baseline" C++, i.e. I'll shy away from something that's only in C++11 or something. And I'm especially leery of the overhead and complexity of packages like sigc and boost, so I'll be unlikely to want to use one of their special containers or allocators, either.
std::listshould work well for this scenario. - πάντα ῥεῖstd::unique_ptrprovides you with an automatic destruction. store the nodes in astd::vector<std::unique_ptr<TreeNode>>. you can of course implement your own version ofunique_ptrif C++11 is an absolutely no-go for you. - m.s.