Archived

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

HydroX

(C++) Constructers, Deconstructers?

Recommended Posts

HydroX    122
Hey do you guys mind explainig me what they are... I am up to the part of classes in c++ and dont understand this part.. why do you need constructers and deconstructers? what are they for ty

Share this post


Link to post
Share on other sites
Palidine    1315
basically to get and free the memory for a class.

so if i have a class foo is say:

Foo * pfoo = new Foo();

then later on:

delete pfoo;


new Foo(); calls the constructor and generates a new Foo object.

delete pfoo removes the object from memory.

the really useful thing about contstructors, anyway is that you can create several ways to construct the object by writing multiple constructors. thus you could define a constructor:

public Foo::Foo(int p, int z) {
this->p = p;
this->z = z;
}

with this constructor you can call:

Foo * pfoo = new Foo(3,4);

and the pretend member variables p and z will be initialized to 3 and 4 respectively.

basically if you're just starting classes it probably means you don't know object oriented programming yet. in that case, it'll be confusing as hell but you will pop to awareness of it all once you get a decent grasp of object oriented programming.

Edited by - Palidine on February 7, 2002 5:26:54 PM

Share this post


Link to post
Share on other sites
TerranFury    142
For starters...

Constructors:
- Allocate memory
- Initialize variables

Destructors:
- Free memory

These are the most basic tasks performed by constructors and destructors. However, in reality, a constructor is really just a member function that is called whenever an object is created, and a destructor is called whenever it is deleted.

Here''s an example of a simple class that wraps the functionality of an array:
  
class myIntArray
{
private:
int * ptrArry;
public:
Array(int size)
{
ptrArry = new int[size];
}

~Array()
{
delete [] ptrArry;
}

int get(int n)
{
return ptrArry[n];
}
};

Share this post


Link to post
Share on other sites
crouilla    122
Constructors and Destructors are used to initialize and deintialize members of the class. The Constructor can be used in any class, to set default values for variables. The Destructor is generally used to deallocate memory that may be allocated in the class.

Say I have the following class, which will be used to hold a dynamic number of integers:

class testClass
{
int *iTest;

testClass(int num);
~testClass();
}

testClass::testClass(int num)
{
iTest = new int[num];
}

testClass::~testClass()
{
if (iTest) delete iTest;
}

Anyway, when I create a "testClass" instance, it will run the constructor (it will allocate memory). When I delete the instance, it will run the destructor (which deallocates the memory).

void main()
{
class testClass* t = NULL;

//the following calls the constructor with "num" set to 20
//the constructor then allocates 20 x sizeof(int) for iTest
t = new class testClass(20);

//.... you would use the variable t here ....

//The following causes the destructor to run. This would
//deallocate the memory that was reserved for iTest
if (t) delete t;
}

This is a fairly small example that doesn''t do much, but here''s the thing. Say that I created a thousand iTest objects, and on average, they were called with a "num" of 100. That would be 1000 x 100 x sizeof(int) (4 in most cases), or 400000 bytes of memory that would be allocated. If the destructor didn''t destroy them, that would be nearly half of a meg of memory that would be unavailable to your system until you rebooted.

So, basically, any memory you allocate for a class, or any system resources that you take control of, you need to release back to the system. The best way to do this is through the destructor (since it is pretty much self-contained in the class -- when the class instance goes away, then all of the memory that is used by the class should go away, as well).

One last note:

If you create actual instances of a class (as opposed to pointers to the object), the object is destroyed (and the destructor called) once the object loses focus (once the function where the object is created exits):

void testFunction()
{
class testClass x(20);

//code goes here...

//once function exits, the testClass object is destroyed,
//and the destructor is run
}

Hope this helps.

-Chris

Share this post


Link to post
Share on other sites
coderDavis    122
Just extending what Palidine said...

You only need constructors and destructors for Classes. A primative (such as an int) doesn''t need a constructor because all C++ compilers already know how to handle it.

When you say

int freddy;

You are asking the computer to allocate 32 bits (4 bytes) of main memory (the stuff on your CPU and RAM chips), and you are naming those four bytes "freddy". You are telling your OS "hey! nobody else gets to mess with freddy!" effectively putting a velvet rope around those 4 bytes until you''re done with them.

When you say

freddy++;

you are manipulating the value which is stored across those 4 bytes (in this case, by adding 1 to it).

When next you say

return;

freddy goes out of scope. This means your program no longer needs freddy, so the compiler tells the OS to disregard that velvet rope and "freddy" evaporates into obscurity (without the rope to protect him, freddy''s gonna get written over by some other variable -- his seats get taken by somebody else and nobody even remembers who freddy was -- he was "destructed").

But, if you create a Class (a type of object, like Paladine''s Foo) you''re building something that your compiler isn''t so intimately familiar with (maybe a Foo just contains two pointers, or maybe it''s a big graphic routine with all sorts of interactivity and error checking member functions), whatever it is, YOU have to tell the compiler how to lay out and manage the velvet rope. Otherwise it has no idea what a Foo* is.

A function that lays out that rope is called a constructor.

You also have to tell the compiler how to pick that rope back up (sometimes it''s not as easy as running the constructor in reverse). You also have to tell it WHEN to pick up the rope (otherwise, the rope never gets picked up, and you have bigger and bigger chunks of uselessly reserved memory leaking out).

A function that picks the rope up again is a destructor.

Why the rope at all? Without it, a reference to freddy or to pfoo or to any variable name is meaningless. The rope is actually a pointer or set of pointers (they sometimes show up in error windows looking like 0x003E94A8 or somesuch hexadecimal value) which correspond to tiny physical seats of memory (a memory cell, called a flip-flop, made of a few microscopic wires on your memory DIMM or CPU cache -- millions of which sometimes show up hanging on hooks in Best Buy or Circuit City).

These pointers tell your compiler where to look for freddy''s value(s)--which seats are reserved for freddy--which memory units should be read in which order for your program to know everything it needs to know about freddy.

C++ "knows the ropes" of primatives, but not of more advanced objects (like a Foo, whatever that is). Constructors and destructors teach your compiler the ropes of your Class. "new" tells it when to create an instance of the class (lay out the ropes), "delete" tells it when to destroy an instance, to pick those ropes back up again. (ALWAYS REMEMBER, pick ''em back up.)

Because programmers call these complicated things "objects" (as opposed to "simpler" things like primatives or methods), learning to write Class methods (especially essential ones like constructors and destructors) is part of "Object Oriented Programming" (OOP).

Hope that helps.

Share this post


Link to post
Share on other sites
merlin9x9    174
Contrary to what the other guys were essentially suggesting, you do not need to use new and delete to make constructors and destructors work. As the last poster implied, any object, no matter where its allocated, will have its constructor called upon instantiation and its destructor called when it goes out of scope. In other words, you can do this:
  
int function()
{
myclass a; <-- constructor called here
...
} <-- a goes out of scope here, so its destructor is called


Unless you truly need your object to be allocated at run time, DO NOT use new and delete to make it so. This will lead not only to a performance penalty (and eventual memory fragmentation), but it introduces the potential for more bugs since it''s so easy to forget delete or to use the wrong version of it. I see people around here using new and delete as if they figured C++ were Java—which takes care of memory for you. Don''t get into that habit (trap).

Also, you don''t have to create a constructor and/or destructor for your class if you don''t have any initialization/finalization (respectively, and separately) to perform. For example, unless your class dynamically allocates some memory or opens some resource, you won''t need a destructor. If it does, for the love of God don''t forget a destructor to release the memory/resources. If your class needs memory or resources, or just plain [member] initialization when its instantiated, then you''ll need a constructor or two.

Both classes and structs can have constructors and destructors because they are literally the same, except that structs has public members by default, rather than private as in classes.

Share this post


Link to post
Share on other sites
DrPizza    160
quote:
Original post by merlin9x9
Unless you truly need your object to be allocated at run time, DO NOT use new and delete to make it so. This will lead not only to a performance penalty (and eventual memory fragmentation), but it introduces the potential for more bugs since it''s so easy to forget delete or to use the wrong version of it. I see people around here using new and delete as if they figured C++ were Java—which takes care of memory for you. Don''t get into that habit (trap).

It is very easy to get it right every time. As soon as you write new or new[], write delete or delete[], and write what''s using the code in between the new/delete pair. That will cover the vast majority of cases and leave you immune to such leaks. The cases it won''t cover are probably cases that can''t use stack allocations anyway (for instance, allocating memory in one routing and passing it to another).

Share this post


Link to post
Share on other sites
Shannon Barber    1681
ctor''s don''t allocate memory, and dtor''s doesn''t deallocate memory either (unless you write code in them to do so).

new calls an object''s constructor after acquiring memory, and delete calls the destructor before releasing the memory.

Share this post


Link to post
Share on other sites
merlin9x9    174
Then I suppose, DrPizza, that you'd be surprised how incredibly often I see people get it messed up. Beyond that, why dynamically allocate when you simply don't need to? I'm not saying that you should never do it, but just do it when it's actually necessary to avoid the possibility of screw-ups—since it's impossible to screw up stack-based objects in this regard, and possible to screw up dynamically-allocated ones, the latter are intrinsically and inarguably more "risky."

Edited by - merlin9x9 on February 7, 2002 11:24:33 PM

Share this post


Link to post
Share on other sites
DrPizza    160
quote:
Original post by merlin9x9
Then I suppose, DrPizza, that you''d be surprised how incredibly often I see people get it messed up.

Yes, really. Unless you''re doing something where you can''t simply write the delete after the new, there''s no reason to write memory leaks.

If you''re doing something more complex (for instance, I have code where I have two threads communicating through an I/O completion port; one thread creates objects and posts pointers to them to the port, the other thread waits on the port and manipulates the objects then deletes them -- there is complication because the allocation and deallocation are necessarily divorced from each other), you have to be more careful, certainly. But for most cases, it''s as simple as writing the delete straight away.

quote:
Beyond that, why dynamically allocate when you simply don''t need to? I''m not saying that you should never do it, but just do it when it''s actually necessary to avoid the possibility of screw-ups—since it''s impossible to screw up stack-based objects in this regard, and possible to screw up dynamically-allocated ones, the latter are intrinsically and inarguably more "risky."


Because running out of stack space is generally more likely than fragmenting my memory space such that I can no longer allocate more memory.

Share this post


Link to post
Share on other sites