Sign in to follow this  
AntonioR

2D std::vector problem

Recommended Posts

AntonioR    309
Hi, I need a little help with 2D vectors.

So, I have a Sprite object which has a 2D vector "coll_box" as seen below. It should hold some Vector3 pointers (x,y,z). Every row should contain info. on different "collision rectangles" (4 points).

For now I just want to add 4 dots int the first row, but I am not able to "push_back" Vector3, in the vector. The program just crashes.


std::vector < std::vector <Vector3*> > coll_box;

[code]
void eng_Collision::setColl_box(Sprite *a)
{

a->setCollisionMethod(B_RECT);

//1 2
//4 3
Vector3 *dot1 = new Vector3();
dot1->Set(a->getX(),a->getY(),0);
a->coll_box[0].push_back(dot1);

Vector3 *dot2 = new Vector3();
dot2->Set(a->getX()+a->getWidth()*a->getScale(),a->getY(),0);
a->coll_box[0].push_back(dot2);

Vector3 *dot3 = new Vector3();
dot3->Set(a->getX()+a->getWidth()*a->getScale(),a->getY()+a->getHeight()*a->getScale(),0);
a->coll_box[0].push_back(dot3);

Vector3 *dot4 = new Vector3();
dot4->Set(a->getX(),a->getY()+a->getHeight()*a->getScale(),0);
a->coll_box[0].push_back(dot4);

}//setColl_box
[/code]

Share this post


Link to post
Share on other sites
way2lazy2care    790
If you are in debug it should tell you why it crashed.

If you are always holding 4 points, I wouldn't use a vector. Just use an array.

best guess is that your vectors don't exist yet.

Share this post


Link to post
Share on other sites
AntonioR    309
a->coll_box is empty, and I call setColl_box just to add 4 Vector3 object/pointers in the first "row" (just once) .

I never use them for anything but it still crashes the program.

I mentioned that I want to have multiple collision boxes, each one defined with 4 Vector3 points/dots in a different row.

I guess I could use a 1D vector with 4n size, but I need to know how to work with 2D vectors for some other stuff.

Share this post


Link to post
Share on other sites
ksmpal    136
The most likely reason for the crash would be memory access violation at
a->coll_box[0]

[font="Arial"]when a->coll_box is empty.

If you just want to add a new set of Vector3 pointers to a->coll_box, you will need to do a 2-level push_back: one at std::vector <Vector3*> level, then at [/font][font="Arial"]std::vector[/font] < [font="Arial"]std::vector <Vector3* > > level.
Create a temporary variable A of type [/font][font="Arial"]std::vector <Vector3*>, push_back the new-ed Vector3 object pointers into variable A, and then finally push_back A into a->coll_box.[/font]

Share this post


Link to post
Share on other sites
AntonioR    309
[b]NEW QUESTION:[/b]

Hi, like I said above, my sprite class has a 2D vector like this:
std::vector < std::vector <Vector3*> > coll_box;

I am not sure how to properly delete the objects that those pointers point to, and then clear the vector so it is empty.

Should I go trough the vector elements and delete them, and then call vector::clear (twice )?
Is that the right approach?

Share this post


Link to post
Share on other sites
kauna    2922
[color=#1C2837][size=2]Does your vector<Vector *> need to be a pointer?[/size][/color]
[color=#1C2837][size=2]
[/size][/color]
[color=#1C2837][size=2]Wouldn't it be a lot easier to just have [/size][/color][color=#1C2837][size=2]std::vector < std::vector <Vector3> > coll_box;[/size][/color]
[color=#1C2837][size=2]
[/size][/color]
[color=#1C2837][size=2]It would save you from the "new" and "delete" pain.[/size][/color]
[color=#1C2837][size=2]
[/size][/color]
[size="2"][color="#1c2837"]Cheers![/color][/size]

Share this post


Link to post
Share on other sites
rip-off    10979
Do you need to use pointers? Can you store them by value? That would simplify everything, and probably speed up your program too.
[quote]
Should I go trough the vector elements and delete them...
[/quote]
If you're allocating them with new, yes you must delete them.
[quote]
... and then call vector::clear (twice )?
[/quote]
If you clear the outer vector, you are removing all the inner vectors, so you don't need to manually clear them. You shouldn't need to clear anything twice.

Share this post


Link to post
Share on other sites
NightCreature83    5006
[quote name='rip-off' timestamp='1310643364' post='4835213']
Do you need to use pointers? Can you store them by value? That would simplify everything, and probably speed up your program too.
[quote]
Should I go trough the vector elements and delete them...
[/quote]
If you're allocating them with new, yes you must delete them.
[quote]
... and then call vector::clear (twice )?
[/quote]
If you clear the outer vector, you are removing all the inner vectors, so you don't need to manually clear them. You shouldn't need to clear anything twice.
[/quote]

[offtopic]
If you forget to call the delete the OS will still clean it up though after the process has terminated, this doesn't help with your memory situation while running your app though.
[/offtopic]


You shouldn't use clear any way after you called delete on your vectors use the [url="http://www.cplusplus.com/reference/stl/vector/swap/"]swap trick[/url] to set your vectors back to using no memory and let the old one scope out in the temporary var you just created.

Share this post


Link to post
Share on other sites
AntonioR    309
Thanks guys for your help. As you see I don't really know what I am doing here :lol:. I will change it so I don't use pointers anymore.

So then, when I want to completely empty that vector from objects I will just have to do what ? pop_back until it is empty, clear ...?

I need to remove those objects from memory while application is running.

Share this post


Link to post
Share on other sites
Wooh    1088
coll_box.clear(); is all you need to make coll_box empty. coll_box will still occupy some of the old memory after clear() but you most likely don't have to worry about that.

Share this post


Link to post
Share on other sites
AntonioR    309
I want to clear that coll_box vector, so I can fill it up again with new Vector3 objects if necessary.

During the game, sprites sometimes behave just like a dot, sometimes lines (two dots) or rectangles (4). When switching I want to empty it, and fill with new ones.
So I just need to call clear ?

I have one more question: When I delete a sprite that holds that coll_box, do I need to clear that vector then too in the Sprite destructor ?

Share this post


Link to post
Share on other sites
Wooh    1088
[quote name='AntonioR' timestamp='1310658829' post='4835303']When I delete a sprite that holds that coll_box, do I need to clear that vector then too in the Sprite destructor ?[/quote] coll_box's destructor frees all it's memory and will be called after the Sprite's destructor so there is no need to clear it in the destructor.

Share this post


Link to post
Share on other sites
NightCreature83    5006
[quote name='rip-off' timestamp='1310656563' post='4835285']
You can just scope the vector such that it is destroyed when you are finished using it. Re-using objects can be a source of bugs.
[/quote]

When you put an object in an STL Container, the container assumes ownership of this object, what this means is that when you push an object into the container it will make a copy of this object. When you call clear on this container it will call the destructor on each element that is in the vector and set the size of the vector back to 0, this is not the capacity which is how much memory the container is actually using.


If a std::vector is part of a class this scope trick won't work on the member and when you want to clear the memory the vector is taking you need to make a new vector with capacity 0 and swap this with the vector in the class. The temporary vector you just created will now scope out and be destroyed and with it it will destroy all the objects it contains, so you don't have to call clear on this temp vector. This is whats known as the "swap trick".



[quote name='Wooh' timestamp='1310659083' post='4835304']
[quote name='AntonioR' timestamp='1310658829' post='4835303']When I delete a sprite that holds that coll_box, do I need to clear that vector then too in the Sprite destructor ?[/quote] coll_box's destructor frees all it's memory and will be called after the Sprite's destructor so there is no need to clear it in the destructor.
[/quote]


When an instance gets destroyed all the destructors of the member variables are called when the body of the class that is being destroyed has finished executing. You would normally only provide a destructor implementation if you use dynamic memory in any of the member variables as in they are newed somewhere during the lifetime of this instance, or when you need to release resources that this class is using, think of textures, file handles etc.




Share this post


Link to post
Share on other sites
rip-off    10979
I am aware of the swap idiom. Forcing the vector to deallocate the memory isn't necessarily a good idea, especially on a vector of vectors. Reallocations of the "outer" vector cause large amounts of work moving the "inner" vectors, for non-move constructor aware compilers.

If the outer vector is merely clear()ed, it may retain its allocated size, which means that if one starts pushing vectors into it these will likely not cause reallocations for the outer vector. Once the size of the outer vector has "peaked", all allocates will be those performed on the inner vector.

Whether the inner vectors needs to be removed, clear()ed or even left alone isn't obvious from the OP's request. I'm still not sure the purpose of this two dimensional vector of vector of Vector. If we had a better idea of what is the high level goal here?

[quote]
If a std::vector is part of a class this scope trick won't work...
[/quote]
If the vector is truly temporary, it should not be a member of a class that outlives it. Restructuring the code such that the vector naturally goes out of scope would be better.

Share this post


Link to post
Share on other sites
AntonioR    309
[quote name='rip-off' timestamp='1310660830' post='4835317']
Whether the inner vectors needs to be removed, clear()ed or even left alone isn't obvious from the OP's request. I'm still not sure the purpose of this two dimensional vector of vector of Vector. If we had a better idea of what is the high level goal here?
[/quote]

OK, namings probably confuse.

Vector3 object holds x,y,z positions , in coll_box case it holds positions of collision points (which can form a line, a rectangle...). coll_box is a member of Sprite objects.

coll_box is 2D because sprites can have multiple "collision boxes" (for head shots and stuff). Each row in the vector would then be a different collision box, containing points (vector3).

Because the number of collision boxes or points can be changed during the life of the Sprite, I want to remove the "inner vectors" completely and its contents, like they never existed. That would have to leave an empty outer vector that I can fill again.

So, the outer vector that holds the inner ones doesn't need to be removed, just emptied like written above.

Share this post


Link to post
Share on other sites
Aardvajk    13207
If col-boxes always contain exactly four points, a resizable container like a vector is not the best way to represent them.

[source lang="cpp"]
struct box
{
Vector3 left,top,right,bottom;
};

std::vector<box> boxes;

void f()
{
box b;
b.left=Vector3(1,2,3);
// etc

boxes.push_back(b);

// blah blah

boxes.clear(); // but as rip-off says, refactor so lifetime matches usage
}
[/source]

This will avoid a great deal of confusion, reduce the amount of memory allocations and probably be far more cache friendly.

Equally, box could be represented by a centre point and three floats representing the half-dimensions of the box, halving the size of the structure but this is likely irrelevant.

Share this post


Link to post
Share on other sites
NightCreature83    5006
[quote name='AntonioR' timestamp='1310664726' post='4835345']
[quote name='rip-off' timestamp='1310660830' post='4835317']
Whether the inner vectors needs to be removed, clear()ed or even left alone isn't obvious from the OP's request. I'm still not sure the purpose of this two dimensional vector of vector of Vector. If we had a better idea of what is the high level goal here?
[/quote]

OK, namings probably confuse.

Vector3 object holds x,y,z positions , in coll_box case it holds positions of collision points (which can form a line, a rectangle...). coll_box is a member of Sprite objects.

coll_box is 2D because sprites can have multiple "collision boxes" (for head shots and stuff). Each row in the vector would then be a different collision box, containing points (vector3).

Because the number of collision boxes or points can be changed during the life of the Sprite, I want to remove the "inner vectors" completely and its contents, like they never existed. That would have to leave an empty outer vector that I can fill again.

So, the outer vector that holds the inner ones doesn't need to be removed, just emptied like written above.
[/quote]

All we are saying is that it is better to have a std::vector< BoundingBox > instead of std::vector< std::vector< Vector3 > > and bounding box can be defined as


struct BoundingBox
{
Vector3 m_corners[4];
}

This would give you a better allocation per collsion box than having another vector in the vector. Besides if you clear the outer vector all your bounding boxes would be gone at that point. Also it increases the maintainability and readability of your code.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this