3

Alright, this has had me stumped on and off for a couple of months now, so I'll see if anyone else can help with this.

So in my main program I have two kinds of structs (solarBody_t, ship_t) that are both derived from the same base class (physical_t). I make a vector of both objects, since I can't put a solarBody and a ship in the same vector. They are both dumb pointer vectors.
I tried putting both in the same vector, using a vector of boost::shared_ptrs. Now, to my understanding, shared_ptrs should have the same semantics and syntax as dumb pointers (e.g. foobar->mass = 42; should work for both). However, just changing the declaration to a vector of boost::shared_ptr to dumb pointers, it gives me an error when I try and push_back something to the vector of shared_ptrs.

From what I can tell, this should work. The boost docs give the example of

boost::shared_ptr<int> p(new int(2));

which is pretty much what I'm doing.

Has anyone had previous experiences with this? Or want to suggest another way to store everything in a vector?

For more details, here's the gist of it (kind of a contradiction of terms, but I made the pun, so there.)

pmelanson
  • 330
  • 4
  • 16
  • 2
    You probably don't want a `shared_ptr`. See [Which kind of pointer do I use when?](http://stackoverflow.com/questions/8706192/which-kind-of-pointer-do-i-use-when). – Jesse Good Jun 06 '12 at 02:00

2 Answers2

3

I don't think it'll let you automatically construct a shared_ptr from a bare pointer. push_back is expecting a shared_ptr<foobar_t>, not a bare foobar_t. You should take a look at boost::make_shared and try something like this:

entity_smart.push_back(boost::make_shared<foobar_t>(42));

make_shared has a few advantages: namely, it allocates the pointer control block and the object itself in one allocation and keeps an unmatched new out of your code. It also makes it explicitly clear that you're creating a shared_ptr to an object.

Other than that, yes, the semantics should be basically the same. Keep in mind that shared_ptr may be overkill for what you're doing, though, if you don't actually need to share ownership of the objects.

Wyatt Anderson
  • 9,612
  • 1
  • 22
  • 25
  • I'd definitely like to minimize overkill, as this program should be as efficient as possible (the target hardware will be kind of slow). Also the purpose of this is to be able to have solarBody_t and ship_t in the same vector, which led to boost::shared_ptr. It sounds like you have a flavour of smart pointer in mind? I'm definitely open to suggestions. – pmelanson Jun 06 '12 at 02:00
  • 1
    You might want to look at [`shared_array`](http://www.boost.org/doc/libs/1_49_0/libs/smart_ptr/shared_array.htm) if you want to tie the lifetime of the contained objects with the array itself, or perhaps [`intrusive_ptr`](http://www.boost.org/doc/libs/1_49_0/libs/smart_ptr/intrusive_ptr.html) if you want to have lower-overhead, managed shared ownership. I dunno how far in depth I can go in just a comment, though. – Wyatt Anderson Jun 06 '12 at 02:03
  • 1
    Basically, there are a lot of design considerations that go into something like this. It might also be premature optimization at this point to nitpick over storage. You can always profile and refactor later. – Wyatt Anderson Jun 06 '12 at 02:04
  • that's probably what I'll end up doing, this project is due in six days. I will have just so much fun choosing containers. So much. Also, thanks for the help and follow-up. – pmelanson Jun 06 '12 at 02:08
2

Lateral thinking:

You do not actually need a shared_ptr here, what you want is a STL(-like) collection in which to store polymorphic values; the collection being the owner.

You have basically two solutions:

  • use a pointer-aware collection: boost::ptr_vector, from the Pointer Container library.
  • use a better pointer: std::unique_ptr, from the C++11 Standard

I would still advise boost::ptr_vector even if you have access to C++11 because it provides additional guarantees (null not allowed by default) and sugar coating (dereferencing an iterator gives a reference, not a pointer than you have to dereference once more).

Matthieu M.
  • 287,565
  • 48
  • 449
  • 722