Vectors of Objects or Pointers?

Started by
4 comments, last by Buckeye 14 years, 1 month ago
I've been using vectors for quite a few things but there's something I haven't quite been able to clearly understand. I think I just misunderstood something about dynamic memory allocation and vectors. What I'm wondering is: Generally, is it best to make a vector of the object you intend to story or a vector of pointers to the objects you intend to store and then use new to have them point to objects? It's probably obvious but I think I got confused early on. Given the pointer's place in C++'s system of dynamic memory I found it strange to add an object rather than a pointer to a vector dynamically. So to clarify, if you're creating a vector to store objects (rather than just point to objects created somewhere else) it's proper to just make a vector of that object type, right? How does that work anyway? Is it just because the vector manages the memory by automatically making new arrays etc. and we don't see what it does? At the lowest level, you need pointers to dynamically allocate memory, right? It's just that whenever people talk about C++ and dynamic memory, they always mention new which obviously returns a pointer. Then we have vector which can be used to dynamically allocate memory but you can use objects with it. Generally I've just stuck to using vectors of pointers since I know that works.
Advertisement
Depends. If you use a vector of pointers, then you will typically end up allocating each object separately, and dynamic memory allocation is not very cheap. Memory-wise for example, typically an object allocated on the heap will require an additional 16 bytes (in release mode, more in debug mode) which are used by the runtime for bookkeeping (I'm not very sure though). But if you create a vector of objects, then all objects in the vector will be allocated together in one chunk, and occasionally when the vector is resized, it will need to copy and delete a bunch of those objects. You can't keep pointers to objects stored in an object vector because you can't be sure the vector will not relocate the object in memory as it grows or shrinks, invalidating the pointer you are keeping. Of course, you can resolve this by storing an index rather than a pointer. Also, keep in mind that a vector of pointers still needs to do its own dynamic memory allocation for the pointers themselves, but of course, it doesn't allocate each pointer separately.

So in the end, if the object is rather light, and you don't need to keep pointers to specific objects, then a vector of objects is suitable and will perform better, and will look better in code.

P.S. This is my understanding of this and I can be wrong. If I'm right, then yay! If not then I'm looking forward to learn about it.
Quote:Original post by Amr0
Depends. If you use a vector of pointers, then you will typically end up allocating each object separately, and dynamic memory allocation is not very cheap. Memory-wise for example, typically an object allocated on the heap will require an additional 16 bytes (in release mode, more in debug mode) which are used by the runtime for bookkeeping (I'm not very sure though). But if you create a vector of objects, then all objects in the vector will be allocated together in one chunk, and occasionally when the vector is resized, it will need to copy and delete a bunch of those objects. You can't keep pointers to objects stored in an object vector because you can't be sure the vector will not relocate the object in memory as it grows or shrinks, invalidating the pointer you are keeping. Of course, you can resolve this by storing an index rather than a pointer. Also, keep in mind that a vector of pointers still needs to do its own dynamic memory allocation for the pointers themselves, but of course, it doesn't allocate each pointer separately.

So in the end, if the object is rather light, and you don't need to keep pointers to specific objects, then a vector of objects is suitable and will perform better, and will look better in code.

P.S. This is my understanding of this and I can be wrong. If I'm right, then yay! If not then I'm looking forward to learn about it.


This is mostly right, but if your compiler supports C++0x (MSVC 10, GCC 4.3 and higher, Intel 11) then vector is "move-enabled", which means that even if you store the objects by value, if the objects you're storing provide move constructors then they won't incur a very big performance overhead because you'll never be copying objects, only moving them. You should get performance gains on any types of objects but you'll see the biggest gains with objects that are expensive to copy for whatever reason (dynamic memory allocation, unmanaged resource acquisition, etc).

For example, if you have a vector of strings, then every time it grows it has to resize the internal vector buffer, copy-construct all the strings into their new location, and then delete all the old strings. That's at least 2N dynamic memory operations where N is the length of the vector. With a move-enabled vector there's exactly 0 dynamic memory operations. No allocations, no frees.
As a general recommendation, you should prefer containers of objects. If you need polymorphic behavior, you can use a container of shared pointers or a Boost pointer container.

This will minimize the probability of messing things up (memory leaks and such), and will keep the code clear, which should be the first priority when writing code.

Of course there will be cases where such simplistic advice will not be appropriate.
K... think I understand it better now, thanks.

Quote:Original post by Amr0
You can't keep pointers to objects stored in an object vector because you can't be sure the vector will not relocate the object in memory as it grows or shrinks, invalidating the pointer you are keeping. Of course, you can resolve this by storing an index rather than a pointer.


Oooh... right. That makes sense. Didn't think of that :O

Speaking of which, right now I have a class with a vector that will be filled once and should never then have anything added to or removed from it for the whole running of the program. I then have another class which will need to refer to the objects in the vector in some way.

In this case... I suppose it would be safe to use pointers, right? Though probably not good practice. Best just to remember the index then, yeah? I suppose that'd be fine.
Quote:I suppose it would be safe to use pointers, right? Though probably not good practice. Best just to remember the index then, yeah? I suppose that'd be fine.

In that case, just use an index. You're going to allocate memory for each object anyway. Let the vector do it. That also obviates the need to delete or deallocate the objects. That'll happen when the vector goes out of scope.

Also, provided the objects themselves don't new any memory themselves, you may in future want to simple copy one vector to another (for testing, temporary modification, etc.).

Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly.

You don't forget how to play when you grow old; you grow old when you forget how to play.

This topic is closed to new replies.

Advertisement