4

I am just starting to use boost::ptr_vector. I have a ptr_vector pctr as a member of one class A and want another class B to refer to an element in pctr. While constructing an object of class B I want to store a pointer in pctr.

Since pointer containers do not allow access to the pointer (but only to references), I must take the address of the reference from pctr and then store it in the object of type B. But taking the address of a reference seems unintuitive. Is there an better alternative?

amit kumar
  • 20,438
  • 23
  • 90
  • 126
  • Actually have the same issue. Will go back to my previous solution (vector of raw pointers with explicit delete). Silly, really. – Cookie May 28 '11 at 13:43
  • @Cookie actually, till now (2011) I have been using pointer containers a lot. I use a reference_wrapper. I have explained this in the wiki of a project I am working on: http://sourceforge.net/apps/mediawiki/crackpot/index.php?title=Boost_Pointer_Containers – amit kumar Jun 03 '11 at 09:32
  • Good point, thanks. If you find yourself with some spare time, performance comparisons between the three alternatives might be nice. – Cookie Jun 06 '11 at 10:06

2 Answers2

2

As you've discovered, the boost pointer containers guard their pointers well. Sure, you can defeat it by taking the address of the references it will yield, but be aware that you may be diluting the strength of the pointer container's claim to authoritative ownership by hanging on to these pointers (all depends on the rest of your code really).

Alternatives would seem to be:

  • Have class B hold iterators referencing the pointer container element of interest (of course usual iterator invalidation rules will have to be dealt with).

  • Since A owns the pointers and you seem to want B to hold some sort of non-owning weak reference to it, use a container of shared_ptr instead, and have B use weak_ptr. Downside might per performance.

timday
  • 24,582
  • 12
  • 83
  • 135
  • 1
    Ya, I guess the rationale behind the design seems to be that since the ownership of the pointers is with A, B should not have a pointer, but a reference to an element within the pctr. In other words, B's declaration has to be based on the fact that the element within the pctr would always exist. – amit kumar Jun 12 '09 at 11:57
  • Although syntactic sugar, `reference_wrapper` might be just what the doctor prescribed. http://stackoverflow.com/questions/193703/how-is-tr1referencewrapper-useful – amit kumar Jun 18 '09 at 12:10
0

I think taking the address of the dereferenced iterator is the correct way to achieve what you're trying to do.

iterator it = ...
T *ptr = &*it;

However, this is dangerous because you could end up with dangling pointers, if the A object is destroyed before B objects. This is why the release function, which lets the caller take the address of an object, also remove the pointer from the container.

If you can support the overhead, you might consider changing the boost::ptr_vector to a vector of smart pointers, e.g. std::vector<boost::shared_ptr<T> >.

Luc Touraille
  • 79,925
  • 15
  • 92
  • 137