views:

335

answers:

2

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?

A: 

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
The address of the iterator to a ptr_vector would change and become invalid if there is further insertion.
Amit Kumar
but the -1 is not from me (your statement about using vector of shared_ptrs makes sense).
Amit Kumar
+2  A: 

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
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
Although syntactic sugar, `reference_wrapper` might be just what the doctor prescribed. http://stackoverflow.com/questions/193703/how-is-tr1referencewrapper-useful
Amit Kumar