17

I need a container of pointers. Would you recommend boost::ptr_vector<T> or std::vector<boost::shared_ptr<T> >? (Or something else?)

If that's of interest, my actual data structure is relatively complicated (see here) and currently stores objects, not pointers, but i'd like to change that (using pointer containers), in order to get rid of unnecessary copying:

typedef std::multimap<Foo0, std::map<int, double> > VecElem;
std::vector<VecElem> vec;
Community
  • 1
  • 1
Frank
  • 64,140
  • 93
  • 237
  • 324
  • where does this unnecessary copying occur? – Idan K Sep 29 '10 at 14:34
  • @Idan: Anytime you insert something into the vector or the multimap from above. – Frank Sep 29 '10 at 14:40
  • 3
    @Idan: When when you have a container that stores pointers, only the pointer will be copied when adding data, when you store objects, the actual objects will be copied. This is a problem when you are dealing with objects which are expensive to copy. – sbi Sep 29 '10 at 15:46

2 Answers2

32

Who owns the object? If the container owns the objects (meaning the objects should not live longer than the container), use a ptr_vector. Otherwise, use a vector of shared_ptrs. Standard library containers (such as std::vector or std::list) own the objects they contain, so the semantics of a ptr_vector is closer to that.

Björn Pollex
  • 75,346
  • 28
  • 201
  • 283
  • Add'l question: is a `vector` of `unique_ptr` the same as a `ptr_vector`? – Didier Trosset Sep 29 '10 at 14:36
  • @Didier: I do not know enough about `unique_ptr` to answer that question. However, the `ptr_vector` will have less overhead (as @sbi points out in his answer). – Björn Pollex Sep 29 '10 at 14:40
  • 9
    @Didier: no, `ptr_vector` allows copy of the `vector`, which deep copies the content (using `new_clone` free function) and thus allow for polymorphic containers. It also has nicer interface (dereferencing the iterator yields a reference to the object, not a reference to the pointer to the object) and other goodies. – Matthieu M. Sep 29 '10 at 15:29
14

shared_ptr<> does have a shared owner semantic, which is implemented through incrementing and decrementing of reference counts. That comes with some overhead, especially when multi-threading is enabled (because those counters then have to be locked).

If your objects are shared, use shared_ptr<>.
But if they are effectively owned by the container, and should die with the container, and references (pointers) handed out might go dead as well when the container dies, then use pointer containers, because they have less overhead.
If you are unsure, use shared_ptr to be on the safe side. If it turns out you have a performance problem, you can always optimize later. (It's easier to optimize a working system than to get a prematurely optimized system working.)

sbi
  • 219,715
  • 46
  • 258
  • 445
  • 6
    +1 for `It's easier to optimize a working system then to get a prematurely optimized system working.` – balki Aug 16 '12 at 10:14