Originally Posted by
xion
does that mean 40 bytes are allocated on the heap, and the member functions and its variables of that class is on the stack?
Yes, the 40 bytes are allocated on the heap, and your persPtr array likely occupies 400 bytes (assuming 4-byte pointers) on the stack. As for the member functions and their local variables I would have to say for the local variables themselves, yes... they reside on the stack. The functions themselves however reside in an area of memory which I personally would not call the "stack" as is routinely talked about (maybe someone else can correct me or add to this in some way). As an example, let's make a simple test program:
Code:
#include <fstream>
#include <iostream>
using namespace std;
void func1(void)
{
int i;
cout << "Address of local (to func1) variable i: " << &i << endl;
}
void func2(void)
{
int i;
cout << "Address of local (to func2) variable i: " << &i << endl;
cout << "Address of func1 (called from func2) : " << func1 << endl;
cout << "******Calling func1 (from func2)******" << endl;
func1();
}
int main()
{
int i;
cout << "Address of local (to main) variable i : " << &i << endl;
cout << "Address of func1 (called from main) : " << func1 << endl;
cout << "Address of func2 (called from main) : " << func2 << endl;
cout << "******Calling func1 (from main)******" << endl;
func1();
cout << "******Calling func2 (from main)******" << endl;
func2();
return 0;
}
Output using MSVC 6.0:
Code:
Address of local (to main) variable i : 0012FF7C
Address of func1 (called from main) : 0040142E
Address of func2 (called from main) : 00401429
******Calling func1 (from main)******
Address of local (to func1) variable i: 0012FF24
******Calling func2 (from main)******
Address of local (to func2) variable i: 0012FF24
Address of func1 (called from func2) : 0040142E
******Calling func1 (from func2)******
Address of local (to func1) variable i: 0012FECC
Of note, the functions always have a fixed address. func1 always has the address of 0040142E and func2 always has the address of 00401429. This indicates to me that their address is fixed in memory regardless of where they are called from. Whether this area of memory can be technically called the stack or not is not something I can say.
The local variables on the other hand are a different matter. Look especially at the last three lines in green. The local variable i in func1 starts with address 0012FF24. After the function exits, i is popped from the stack and we run func2 where its local variable i reports the exact same address as func1's local i variable did. Now func2 calls func1 before it exits and when this happens, func1's local variable i has a different address then when it was first called on its own outside of func2. You should gather from this that the variables for these functions are therefore pushed/popped on/off the stack.
Running the same prog on my Visual Studio .Net compiler I get different addresses, but the same general conclusion can be drawn:
Code:
Address of local (to main) variable i : 0012F5A0
Address of func1 (called from main) : 00404D50
Address of func2 (called from main) : 00404DF0
******Calling func1 (from main)******
Address of local (to func1) variable i: 0012F594
******Calling func2 (from main)******
Address of local (to func2) variable i: 0012F594
Address of func1 (called from func2) : 00404D50
******Calling func1 (from func2)******
Address of local (to func1) variable i: 0012F588
Originally Posted by
xion
and on the stack, things are freed automatically where as the heap..the programmer has the power to allocate and is responsible with de-allocating the memory?
Items on the stack are popped for you (destructors get called where appropriate). This includes the memory allocated for any local pointer variable itself but not the memory the pointer pointed to. This allocated memory must be deallocated by the programmer (unless you are using some type of a smart pointer such as an auto_ptr):
Code:
#include <memory>
#include <iostream>
class obj
{
public:
obj() { std::cout << "Constructor called" << std::endl; }
~obj() { std::cout << "Destructor called" << std::endl; }
};
int main()
{
std::auto_ptr<obj> ap(new obj);
// Once ap goes out of scope at end of "main", obj's destructor will be called
}
Output:
Code:
Constructor called
Destructor called