Jump to content
  • Advertisement

Archived

This topic is now archived and is closed to further replies.

graveyard filla

problem with std::list

This topic is 5224 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

high, i have a std::list of Enemy.. (a class in my game)..my game has been working fine the way this pieace of code has been written untill just recently. it looked like this:
Enemy temp; 
temp.Set_X(x*TILESIZE);
temp.Set_Y(y*TILESIZE);
enemy.push_back(temp);
  
i changed some stuff with my Enemy class and all of a sudden my game started crashing at this line enemy.push_back(temp); any, after playing around, i got it to stop crashing by doing this:
Enemy temp* = new Enemy(); 
temp->Set_X(x*TILESIZE);
temp->Set_Y(y*TILESIZE);
enemy.push_back(*temp);
  
why is the second code working and not the first? i have a global list called list < Enemy > enemy; and i dont know why this is happening. i dont want to have to allocate memory if i dont have to.. thanks for any help! [edited by - graveyard filla on June 6, 2004 5:22:29 AM]

Share this post


Link to post
Share on other sites
Advertisement

I'm not really sure, but I think you might want to store the pointers to the Enemy objects and not the enemies itself to the list, the latter will make an addititonal copy-constructor call. What I mean is that if you have:


std::list < Enemy > enemy; // initialized somewhere before
Enemy temp;
// initialize temp
enemy.push_back(temp); // will cause the copy of temp to be stored in the list

It is actually ok if you have properly created a copy constructor for the object & don't mind the extra copy. But if you write it like this:


std::list < Enemy* > enemy; // Now accepts pointers to class Enemy
Enemy *temp = new Enemy;
// initialize temp
enemy.push_back(temp); // will just pass the pointer


Now there won't be any extra initialization. But of course you need to delete all the initialized enemies from the list when your program closes.

What comes to your weird crash, I don't really know what causes it. Perhaps it might be something in your copy constructor?

[edited by - clb on June 6, 2004 5:12:46 AM]

Share this post


Link to post
Share on other sites
hey,

actually, i just forgot to put the * in my example. i do of course push_back(*temp) and not the actual pointer.. i would get an error if i tried that..

i didnt make a copy constructer.. do you think this is why its happening? and what should my copy constructor do? thanks for any help

Share this post


Link to post
Share on other sites
If your class contains pointers, then not having a copy constructor is probably the cause of the crash.

The new object will get a copy of the pointer, and when the old instance of the object is destroyed, it will free the data, and the new instance''s pointer won''t be valid anymore.

Share this post


Link to post
Share on other sites
I think it's an issue with references and structures - I've seen this sort of behaviour a lot, with random bits of unchanged code suddenly starting to crash.

I think the following piece of code should replicate the problem:



struct TestStruct
{
float foo;
int bar;
};

void main()
{
TestStruct t1;
TestStruct t2;

TestStruct& rt1 = t1;
TestStruct& rt2 = t2;

// this is where problems start happening:

rt1 = rt2;
}


I'm not entirely sure why that happens - it's almost as though the compiler gets confused by that last line and just does something more or less random - thus it can work correctly on one build, but fail in another. The solution is, avoid that kind of syntax as much as possible. I believe the STL uses references extensively, so something similar may well be happening in your list.

EDIT: in my experience, adding a copy constructor does not necessarily fix the issue. I'm not sure why graveyard filla's solution works - it may just be that it's forced the compiler to build that piece of code differently again.

EDIT 2: Duh, I just noticed you said you'd changed your enemy class slightly, and that you don't have a copy constructor. So most of my post is probably irrelevant.

[edited by - Sandman on June 6, 2004 5:37:43 AM]

Share this post


Link to post
Share on other sites
so i have to make a copy constructor? and what do i have to do in it so the pointers dont get screwy?

[edited by - graveyard filla on June 6, 2004 6:07:41 AM]

Share this post


Link to post
Share on other sites
quote:
Original post by graveyard filla
so i have to make a copy constructor? and what do i have to do in it so the pointers dont get screwy?



Either a deep copy or reference counted shallow copy

Deep copy: You create a completely new copy of the data that the pointers are pointing to.

Shallow copy: You share the same piece of data between copied objects. However, if you delete this data in the destructor, you'll need to reference count it so that you don't delete it before it's finished with.

Which you choose depends on your requirements, the data being copied etc. Reference counted shallow copies are probably preferable in most cases, (faster, use less memory) but if you want to create a copy of an object and then edit it's data independantly of the original, you need a deep copy.

[edited by - Sandman on June 6, 2004 6:13:17 AM]

Share this post


Link to post
Share on other sites
For STL list the type requirements are default constructable and assignable.

If you don't declare any of those a default is generated for you. Default constructor is provided that only constructs each member with its default constructor as well and so on. An assignement operator is also generated that just
a copies each memeber over.

The only time a type doesn't fullfil this requirement is if you've declared that type with those operations as protected/private. It might not be this problem, it maybe something else, can you show us your declaration of Enermy? and what compiler are you using

[edited by - snk_kid on June 6, 2004 7:43:14 AM]

Share this post


Link to post
Share on other sites
Just trying to get things straight in my head here. So you need a proper copy constructor to work with std::vector and std::list incase your class contains pointers. What is the syntax to a copy constructor?

Is it for example:
CVector2 NewVec(5.0f, 2.0f);

or:
CVector2 NewVec;
NewVec.x = 5.0f;
NewVec.y = 2.0f;
CVector2 NewVecTwo = NewVec;


Is it a constructor that accepts paramters or a constructor that gets called when you write down that last line in the 2nd example?

Share this post


Link to post
Share on other sites
its still crashing...ive never made a copy constructor or done operator overloading before. could you explain what exactly it should all look like? my class has a member which is a pointer that i dynamically allocate (which i think is why it suddenly started crashing - i made this member, and now this is happening).. i just dont understand what my CC / = operator should look like. this is what i got so far:

(also, when is my CC called? i have to do something like Enemy enemy2 = new Enemy(enemy1); ? )

also, i couldnt find the answer to this : what happends when my = operator is called? say i do Enemy newenemy = enemy1; what does this do? it calls my = operator, and sends enemy1 as paremters? and newenemy is assigned whatever is returned?


class Enemy : public Character
{
public:

Enemy();
Enemy(const Enemy& cpy);
~Enemy(){//SDL_FreeSurface(health_img);//SDL_FreeSurface(dead_img);

}
Enemy operator = (Enemy cpy);


virtual void Init();
virtual void Update(); //handle input, collision detection, ...


void Render();
void Draw_Health();
bool On_Screen();
int Clicks_Away();

private:


GLuint health_img;
Sprite sprite;
GLuint texture;

};


now in the cpp file..


Enemy::Enemy(const Enemy &cpy)
{
xPos = cpy.xPos;
yPos = cpy.yPos;
xVel = cpy.xVel;
yVel = cpy.yVel;
h = PLAYERHEIGHT; //save player height and width

w = PLAYERWIDTH;
xVel = 0; //speed

yVel = 0;
current_weapon = cpy.current_weapon;
health_img = cpy.health_img;
texture = cpy.texture;
state = cpy.state;
sprite = cpy.sprite;
current_target = cpy.current_target;
ammo = cpy.ammo;
health = cpy.health;
max_health = cpy.max_health;

}

Enemy Enemy::operator = (Enemy cpy)
{
Enemy temp;
temp.xPos = cpy.xPos;
temp.yPos = cpy.yPos;
temp.xVel = cpy.xVel;
temp.yVel = cpy.yVel;
temp.h = PLAYERHEIGHT; //save player height and width

temp.w = PLAYERWIDTH;
temp.xVel = 0; //speed

temp.yVel = 0;
temp.current_weapon = cpy.current_weapon;
temp.health_img = cpy.health_img;
temp.texture = cpy.texture;
temp.state = cpy.state;
temp.sprite = cpy.sprite;
temp.current_target = cpy.current_target;
temp.ammo = cpy.ammo;
temp.health = cpy.health;
temp.max_health = cpy.max_health;

return (temp);
}


current_weapon is a pointer... a Weapons* pointer which i dynamically allocate anytime the character switches weapons (this *current_weapon is a member of Character which Enemy inherits from.. maybe i should make a copy constructor for Character instead?) i think i should be doing something with this current_weapon, altho im just doing current_weapon = cpy.current_weapon... thanks for any help!

[edited by - graveyard filla on June 6, 2004 2:10:15 PM]

Share this post


Link to post
Share on other sites

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!