Destructors

Started by
20 comments, last by Fruny 17 years, 7 months ago
I just want to clear something up. So, if I have a class with dynamically allocated memory, and it has a destructor that frees that memory, and I have a program that uses it like this: int main() { Class myClass; return 0; } It will call the destructor when it goes out of scope? I don't have to call it manually?
Advertisement
Yes it will automatically be called.
You can test this by putting a breakpoint inside the destructor.

Edit: Yes, I did mean destructor

[Edited by - Deventer on August 13, 2006 12:53:04 AM]
You mean destructor?

Thanks! Then I don't have to manually call all my "Destroy" methods for my wrapper classes, lol.
If you dynamically allocate, i.e. like the following sample:

class A{public:  A();  ~A();};int main(){  A* a = new A();  delete a; // <-- if you don't have this the destructor won't be called}


you have to make sure you have a call to delete as well to match every new call you do, unless dealing with an array where you want to call delete[]
If an object is statically allocated, its destructor is called when it goes out of scope. If an object is dynamically allocated, its destructor is called when you use delete on the appropriate pointer.

Please note this important rule of thumb: when a class implements a custom destructor, copy constructor or assignment operator, it usually needs all three of them.

A typical example of why it is so is when your class contains a pointer and a destructor that deletes it. With the default copy operation, the pointer itself is simply copied, which means that you now have two objects that share the same pointer. When the first object is destroyed, the memory is released. The second object is then left with a dangling pointer which will at the very least cause problem upon destruction of that second object. Similarly, the default assignment will overwrite the pointer in the object you are assigning to, causing a memory leak, and leave you in the same situation as with copy construction, with aliased pointers. You thus need to either make sure copying is done properly, either by reference counting the pointer, or by making a deep copy -- depending on the semantics you wish to implement, or purely and simply disable such copying, by declaring the copy constructor and assignment operator private and not providing an implementation, which will cause a compile-time error if a copy is attempted.
"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." — Brian W. Kernighan
Quote:It will call the destructor when it goes out of scope? I don't have to call it manually?


You can test the behaviour like this:
#include	<string>#include	<iostream>class Foo{public:	Foo() : m_name()	{		std::cout << "Default constructor called." << std::endl;	}	Foo(const std::string & name) : m_name(name)	{		std::cout << "Constructor for " << m_name << " called." << std::endl;	}	~Foo()	{		std::cout << "Destructor for " << m_name << " called." << std::endl;	}	void SetName (const std::string & name)	{		m_name = name;	}private:	std::string m_name;};int main (){// Dynamic	Foo * pf = new Foo("DynamicFoo");	delete pf;// Dynamic Array	Foo * pfa = new Foo [2];	pfa[0].SetName("DynamicFooArray_0");	pfa[1].SetName("DynamicFooArray_1");	delete [] pfa;// Static	Foo sf("StaticFoo");// Static Array	Foo sfa [2];	sfa[0].SetName("StaticFooArray_0");	sfa[1].SetName("StaticFooArray_1");	return 0;}

Thanks everyone! I've got it now.
Just wondering why noone mentioned std::auto_ptr in this context.

Maybe take a look at this article:
http://www.gotw.ca/publications/using_auto_ptr_effectively.htm

Instead of storing a raw pointer to some data inside your instance, you may store an auto_ptr in your instance wrapping that data pointer. This way the data will be deleted automatically when the instance containing the auto_ptr is deleted.
Actually, this all brings up another of my questions. Why use "New"? It seems like you can always just say "Class myClass;" rather than "Class myClass = new Class".
First off, "Class myClass = new Class;" will not compile (myClass needs to be a Class*, not a Class).

Now. There are a lot of reasons for using dynamic allocation.

For one, static allocations have a fixed scope and lifetime (e.g., if it is allocated on the stack within a certain scope, it lives only for that scope; if you want it to live longer you must move it to an external scope (potentially ugly from a design point of view and may involve the use of globals, which introduce their own problems) or dynamically allocate it.

You may need to allocate a number of the objects, and you don't know that number at compile time, so runtime dynamic allocation (directly, or indirectly via std::vector or similar) is required.

Without dynamic allocation, certain data stuctures are anywhere from amazingly difficult to downright impossible to implement.

The object in question might be very, very large and your program might not neccessarly use the object during its runtime, in which static allocation consumes memory you don't need to be consuming.

Stack space is limited, if an object is too big you may basically have to allocate it on the heap.

And so on. There are plenty more. Note that it's of course generally preferable to use a class that manages your memory for you -- an auto_ptr, shared_ptr, vector, et cetera as appropriate, but that's not really the scope of this thread.

This topic is closed to new replies.

Advertisement