Vectors in classes
Kauhiz

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?

Trezker

vector as in std::vector?
Sure.

#include <vector>
class meh
{
  std::vector< float > m_vector;
};

Kauhiz

Cool, thanks! I just thought that there might be some quirks with the vector allocating memory if I put it into a class.

CursedTyrant

I do that all the time.

TeamTerradactyl

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 :)

Ariesnl

... 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;

X-G

Don't listen to that. There's no innate reason why you shouldn't be putting objects in vectors or lists.

Archon
Quote:

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.

Ariesnl
Quote:

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 ::)

Kauhiz
Quote:

Just make sure that you also clean up the vector - perhaps in the class's destructor.

Got it, thanks! :)

Archon
X-G said:

Don't listen to that. There's no innate reason why you shouldn't be putting objects in vectors or lists.

ariesnl said:

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.

HoHo
Quote:

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?

Ariesnl

it was an example, pointers in lists ( and vectors) are more efficient.

It's a little more work, but it it's worth it

Quote:

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.

HoHo
Quote:

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.

Kris Asick

I recently (as in, yesterday) tried stuffing my T_PAGE object into a vector. It contains the following:

struct T_PAGE
{
  BITMAP *bitmap, *stencil;
  PALETTE palette;
  char *filename;
};

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

HoHo

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 :)

Kris Asick

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

X-G

... 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?

Kris Asick

Nothing I haven't done a million times before:

1int 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 
12void T_PAGE::Set_Palette (PALETTE *pal)
13{
14 memcpy(&palette,pal,sizeof(PALETTE));
15}
16 
17T_PAGE::T_PAGE (void)
18{
19 bitmap = NULL; stencil = NULL; filename = NULL;
20 accessed_before = 0;
21}
22 
23T_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

X-G
T_PAGE::~T_PAGE (void)
{
  destroy_bitmap(bitmap);
  destroy_bitmap(stencil);
}

Whoops! :P 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.

tobing

X-G is right, and this means you need to implement operator= and copy constructor for T_PAGE.

Kris Asick

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

tobing

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.

Thread #589538. Printed from Allegro.cc