So far I've been mostly programming in C and using allegro for my projects. A while back I decided to try OpenLayer and I really like it. So I figured if I'll start using OL, I might as well start writing in C++. So I've been reading up on it, and I came up with a question that I haven found the answer to: can I use a vector as a member in a class?
vector as in std::vector?
Sure.
#include <vector> class meh { std::vector< float > m_vector; };
Cool, thanks! I just thought that there might be some quirks with the vector allocating memory if I put it into a class.
I do that all the time.
Kauhiz, actually, I prefer using vectors inside of classes (when array are needed, of course), since they are automatically cleaned up when your object goes out of scope. It makes debugging SEGFAULTs 10x easier
... As for stuffing complete objects in a vector DONT !!
and maybe you'd better use list.
Make a vector or list of pointers to your objects
using namespace std;
list <myClass *> m_lstItems;
Don't listen to that. There's no innate reason why you shouldn't be putting objects in vectors or lists.
I just thought that there might be some quirks with the vector allocating memory if I put it into a class.
Just make sure that you also clean up the vector - perhaps in the class's destructor.
Don't listen to that. There's no innate reason why you shouldn't be putting objects in vectors or lists.
Really ?
how about speed when doing a Z sort
Just make sure that you also clean up the vector - perhaps in the class's destructor.
Got it, thanks!
Don't listen to that. There's no innate reason why you shouldn't be putting objects in vectors or lists.
how about speed when doing a Z sort
Well, there wasn't any mention of Z-sorting. And, he said vectors or lists and you provided a example of a list.
how about speed when doing a Z sort
What about it?
But how about memory fragmentation and having to manually clean up the pointer vector?
it was an example, pointers in lists ( and vectors) are more efficient.
It's a little more work, but it it's worth it
What about it?
But how about memory fragmentation and having to manually clean up the pointer vector?
stuffing Objects in a list or a vector won't help with memory fragmentation.
stuffing Objects in a list or a vector won't help with memory fragmentation.
Vector of 10000 pointers to objects will roughly have 10001 separate memory fragments (assuming objects themselves don't have pointers). Vector of 10000 objects will be in 1 memory fragment. I see a slight difference in numbers. Of cource with linked list things are rather ugly anyways 
I don't put objects straight to container only when they are massive (>~100 bytes) and when I have to sort them. When I only have massive objects with no(little) sorting or have to sort small objects I put them straight to the container. There is little point in wasting 4(8) bytes per pointer in most cases 
Also when I have to sort a container I would never use a list. Vectors are way more effective when needing to sort. Actually there quite a very few cases when lists should be used in place of vectors.
I recently (as in, yesterday) tried stuffing my T_PAGE object into a vector. It contains the following:
If I tried to store more than one, for some inexplicable reason, pieces of every allocated BITMAP pointer were getting overwritten.
All I did was switch to storing pointers to T_PAGE objects instead of the objects themselves and my code started working.
--- Kris Asick (Gemini)
--- http://www.pixelships.com
Without any knowledge of your code I'd say you have a memory leak somewhere that tends to overwrite stuff. By moving to pointers you simply overwrite something else and so far it doesn't show up
I dunno... the only thing that could be wrong is the allocation of the object, but doing T_PAGE() was the only thing the compiler would accept.
Here's the original code. Using this code, all the data in the first T_PAGE object gets screwed up when I create the second one.
std::vector<T_PAGE> page; try { page.push_back(T_PAGE()); } catch (...) { CallErrorHandler(5); } if (page[0].Make_Bitmap(option.xres,option.yres)) CallErrorHandler(5); page[0].Set_Palette((PALETTE*)data[Default_Palette].dat); page[0].accessed_before = 1; clear_bitmap(page[0].bitmap); try { page.push_back(T_PAGE()); } catch (...) { CallErrorHandler(5); } if (page[1].Make_Bitmap(option.xres,option.yres)) CallErrorHandler(5); page[1].Set_Palette((PALETTE*)data[Default_Palette].dat); clear_bitmap(page[1].bitmap);
And here's the new code that works perfectly.
std::vector<T_PAGE*> page; try { page.push_back(new T_PAGE); } catch (...) { CallErrorHandler(5); } if (page[0]->Make_Bitmap(option.xres,option.yres)) CallErrorHandler(5); page[0]->Set_Palette((PALETTE*)data[Default_Palette].dat); page[0]->accessed_before = 1; clear_bitmap(page[0]->bitmap); try { page.push_back(new T_PAGE); } catch (...) { CallErrorHandler(5); } if (page[1]->Make_Bitmap(option.xres,option.yres)) CallErrorHandler(5); page[1]->Set_Palette((PALETTE*)data[Default_Palette].dat); clear_bitmap(page[1]->bitmap);
Practically identical.
--- Kris Asick (Gemini)
--- http://www.pixelships.com
... except there's more code that you're not showing us. What is Make_Bitmap? Set_Palette? What else is hiding in T_PAGE that you're not showing us?
Nothing I haven't done a million times before:
| 1 | int T_PAGE::Make_Bitmap (int xres, int yres) // Return 1 on failure. |
| 2 | { |
| 3 | destroy_bitmap(bitmap); |
| 4 | destroy_bitmap(stencil); |
| 5 | |
| 6 | if ((bitmap = create_bitmap(xres,yres)) == NULL) return 1; |
| 7 | if ((stencil = create_bitmap(xres,yres)) == NULL) return 1; |
| 8 | |
| 9 | return 0; |
| 10 | } |
| 11 | |
| 12 | void T_PAGE::Set_Palette (PALETTE *pal) |
| 13 | { |
| 14 | memcpy(&palette,pal,sizeof(PALETTE)); |
| 15 | } |
| 16 | |
| 17 | T_PAGE::T_PAGE (void) |
| 18 | { |
| 19 | bitmap = NULL; stencil = NULL; filename = NULL; |
| 20 | accessed_before = 0; |
| 21 | } |
| 22 | |
| 23 | T_PAGE::~T_PAGE (void) |
| 24 | { |
| 25 | destroy_bitmap(bitmap); |
| 26 | destroy_bitmap(stencil); |
| 27 | } |
Trust me, this part of the code works perfectly. I spent over half an hour checking it before figuring something must be up with the vectors.
Oh yeah, I renamed "palette" to "pal" at one point. I typed out the class by hand in my first post. 
--- Kris Asick (Gemini)
--- http://www.pixelships.com
T_PAGE::~T_PAGE (void) { destroy_bitmap(bitmap); destroy_bitmap(stencil); }
Whoops!
What do you think happens when this gets called upon vector resizing? That's right, bitmaps get destroyed and eventually thrashed. You need copy semantics for this little baby.
X-G is right, and this means you need to implement operator= and copy constructor for T_PAGE.
No one told me that in any of the tutorials I was reading, in any of the help files, even here on the forums. No wonder I made that mistake...
Still, using pointers instead of the objects themselves seems to work, and is probably faster too, so wouldn't that just be simpler than coding in operator= and copy constructors?
--- Kris Asick (Gemini)
--- http://www.pixelships.com
Using pointers is faster. As discussed, using many single new's may fragment memory - especially if these memory chunks are allocated and freed in random order, and frequently. There's no problem if they are all allocated once and then used.