• Announcements

    • khawk

      Download the Game Design and Indie Game Marketing Freebook   07/19/17

      GameDev.net and CRC Press have teamed up to bring a free ebook of content curated from top titles published by CRC Press. The freebook, Practices of Game Design & Indie Game Marketing, includes chapters from The Art of Game Design: A Book of Lenses, A Practical Guide to Indie Game Marketing, and An Architectural Approach to Level Design. The GameDev.net FreeBook is relevant to game designers, developers, and those interested in learning more about the challenges in game development. We know game development can be a tough discipline and business, so we picked several chapters from CRC Press titles that we thought would be of interest to you, the GameDev.net audience, in your journey to design, develop, and market your next game. The free ebook is available through CRC Press by clicking here. The Curated Books The Art of Game Design: A Book of Lenses, Second Edition, by Jesse Schell Presents 100+ sets of questions, or different lenses, for viewing a game’s design, encompassing diverse fields such as psychology, architecture, music, film, software engineering, theme park design, mathematics, anthropology, and more. Written by one of the world's top game designers, this book describes the deepest and most fundamental principles of game design, demonstrating how tactics used in board, card, and athletic games also work in video games. It provides practical instruction on creating world-class games that will be played again and again. View it here. A Practical Guide to Indie Game Marketing, by Joel Dreskin Marketing is an essential but too frequently overlooked or minimized component of the release plan for indie games. A Practical Guide to Indie Game Marketing provides you with the tools needed to build visibility and sell your indie games. With special focus on those developers with small budgets and limited staff and resources, this book is packed with tangible recommendations and techniques that you can put to use immediately. As a seasoned professional of the indie game arena, author Joel Dreskin gives you insight into practical, real-world experiences of marketing numerous successful games and also provides stories of the failures. View it here. An Architectural Approach to Level Design This is one of the first books to integrate architectural and spatial design theory with the field of level design. The book presents architectural techniques and theories for level designers to use in their own work. It connects architecture and level design in different ways that address the practical elements of how designers construct space and the experiential elements of how and why humans interact with this space. Throughout the text, readers learn skills for spatial layout, evoking emotion through gamespaces, and creating better levels through architectural theory. View it here. Learn more and download the ebook by clicking here. Did you know? GameDev.net and CRC Press also recently teamed up to bring GDNet+ Members up to a 20% discount on all CRC Press books. Learn more about this and other benefits here.
Sign in to follow this  
Followers 0
lonewolff

Safely deleting a class instance

15 posts in this topic

Hi Guys,

I have a vector of classes. How do I safely delete an item in the vector so the destructor gets called.

At the moment I have the following. But I suspect this is a 'brute force' removal.

How do I call 'delete' properly?

[code]for(it=VectorAsset.begin();it<VectorAsset.end();it++)
{
if(szNameOrType==it->szName||szNameOrType==it->szType)
{
//delete it; // <<< wont compile
VectorAsset.erase(it);
}
}[/code]

Any help would be awesome :)
0

Share this post


Link to post
Share on other sites
How did you allocate those class instances ?

If you used new to allocate them you should be able to delete them using

delete *it; // it is a interator pointing to your pointer so you have to dereference it to get your pointer.
then remove the iterator using it = VectorAsset.erase(it); //you have to reassign the iterator since erase will invalidate it.

If you didn't allocate your instances with new you can just call erase and things will get cleaned up, (You still have to reassign the iterator though.
1

Share this post


Link to post
Share on other sites
Thanks for the reply.

I allocated the instances like this;

[code]Asset *cAsset=new Asset(szName,szTexture);
VectorAsset.push_back(*cAsset);[/code]

But, Still can't call delete (where commented above);

Compiler give this error

[b]error C2440: 'delete' : cannot convert from 'Asset' to 'void *'[/b]

This is what I have now;

[code]void SpriteUnload(string szNameOrType)
{
// Erase any valid items from vector array
std::vector<Asset>::iterator it;
for(it=VectorAsset.begin();it<VectorAsset.end();)
{
if(szNameOrType==it->szName||szNameOrType==it->szType||szNameOrType=="ALL")
{
delete *it;
//VectorAsset.erase(it);
VectorAsset.erase(it);
}
else
it++;
}
}[/code]

[edit]
delete &it; worked, though. Edited by lonewolff
0

Share this post


Link to post
Share on other sites
really? It worked?
That seems to be a coincidence.

[code]
Asset *cAsset=new Asset(szName,szTexture);
VectorAsset.push_back(*cAsset);
[/code]

These 2 lines actually push a copy of the asset in the vector. The original Asset pointer is lost in the process.
If you want to store asset pointers use a vector<Asset*> not vector<Asset> and directly push the pointer (without dereferencing).

Since you're posting in "for beginners" I would recommend you read up on smart pointers, especially auto_ptr which is useful in this case. Edited by Madhed
2

Share this post


Link to post
Share on other sites
[quote name='lonewolff' timestamp='1343716472' post='4964732']
[edit]
delete &it; worked, though.
[/quote]

Thats because you were dereferencing your pointer before pushing it to the vector, which would AFAIK create a copy of it (giving you a memory leak).

If you are going to store raw pointers you should use std::vector<Asset *> , if you use std::vector<Asset> you shouldn't allocate them using new.

Edit: Beaten by madhet,

Anyway, if you use std::vector<Asset *> instead it will work with delete *it; and you won't get a memory leak.

You could also look into using smart pointers to avoid the hassle. Edited by SimonForsman
1

Share this post


Link to post
Share on other sites
Thanks for the advice guys!

I have change the code to the following

[b]std::vector<class Asset>(VectorAsset);[/b]

So, when I call [b]VectorAsset.erase(it); [/b]does the destructor get called still? As I have alot of DirectX code that needs to be cleaned up via the destructor (in each instance).
0

Share this post


Link to post
Share on other sites
[quote name='lonewolff' timestamp='1343718777' post='4964747']
Thanks for the advice guys!

I have change the code to the following

[b]std::vector<class Asset>(VectorAsset);[/b]

So, when I call [b]VectorAsset.erase(it); [/b]does the destructor get called still? As I have alot of DirectX code that needs to be cleaned up via the destructor (in each instance).
[/quote]

Yes, the destructor will get called.
0

Share this post


Link to post
Share on other sites
A wierd one. Testing my destructor, it is actually getting called when the class is created. Any ideas why that would be?

[code]~Asset()
{
std::cout<<"Destructing: "<<szName<<"\r\n";
}[/code]
0

Share this post


Link to post
Share on other sites
When you resize a vector, some implementations create a dummy instance, then use that dummy instance in the copy constructor of every new instance in the vector and then free the dummy instance. I guess it is that behavior, that you are seeing.
-1

Share this post


Link to post
Share on other sites
Whenever you insert something into the vector with (for example) [code]myVector[i] = MyClass(...)[/code] or [code]myVector[i].push_back(MyClass(...))[/code] the following things happen:
1) an unnamed instance (let's still call it U to identify it) of MyClass is constructed.
2) a copy constructor (or assignment operator) of the appropriate element in the vector is called for U.
3) U gets destroyed.
Furthermore, whenever you insert or remove elements from the vector, the vector might have to reallocate/reorder its elements, leading to further copy-or-assignment/destructor calls.
0

Share this post


Link to post
Share on other sites
Edit: too slow, too slow...

That would be a horrible work-around. Objects you put into C++SL containers must be copyable and assignable (or movable in C++11). That is usually not a problem because if you put something like std::string into your class it will be handled correctly (because the automatically generated copy and assignment operators of MyClass call the appropriate copy or assignment of std::string) since std::string is (like practically everything in the C++SL) copyable and assignable (and movable in C++1).
Where it will be a problem is with allocated memory. If you allocate memory in the object and store the pointer you will usually free the memory in the destructor. But the default copy constructor/assignment operator will just copy the pointer, no whatever it points to. So continuing the example from above, as soon as U is destroyed the copy points to invalid memory (because it was freed in U's destructor). There are several ways to deal with that:
1) make a deep copy of the allocated memory (that is, the copy constructor and assignment operator must allocate the data themselves and copy the copy over from the source).
2) implement reference counting of some kind so that the data is not deleted until the last instance holding it gets destroyed.
3) use something like boost::shared_ptr or std::shared_ptr (in C++11).

It is worth mentioning the Rule of Three here. If any of your classes needs any of a handcrafted copy-constructor, assignment operator or destructor you in general need to handcraft all three. Edited by BitMaster
0

Share this post


Link to post
Share on other sites
[quote name='lonewolff' timestamp='1343724935' post='4964771']
So, should I ignore the destructors and call a function within the class to handle the cleanup instead?
[/quote]No. When you create a temporary and copy it into a vector, the destructor is still only called once [i]on each instance of the class[/i]. You're seeing it be called twice because you've made two instances -- one temporary and one inside the vector.
This is the correct behaviour when using a temporary.
1

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  
Followers 0