I am learning c++ and would like to know how a program like this is organized in primary-memory. I understand that there are a stack (with stackframes) and a heap. And I know that dynamically allocating something allocates it on the heap. This is done by operators like malloc
or new
. But I cant see them in this small c++ program.
The program consists of a main-class and a class named MyClass
. This class has:
- one constructor
- one member variable (
int
) - one member-function
The main-class defines an object to Myclass and as well defines a pointer to this object.
SO - how are all this organized in memory?
#include
using namespace std;
class MyClass {
int i;
public:
MyClass(int n) {
i = n;
}
int get_nmbr() {
return this->i;
}
};
int main() {
MyClass myClass(100), *p;
cout << myClass.get_nmbr() << endl;
p = &myClass;
cout << p;
return 0;
}
Answer
Let's go through this line by line.
int main() {
A new function starts with this line, and therewith a new scope.
MyClass myClass(100), *p;
Two things happen here. One, a variable myClass
is declared within the function's scope, which makes it a local variable and thus it's allocated on the stack. The compiler will emit machine instructions that reserve enough space on the stack (usually by bumping the sp
stack pointer register), and then a call to the class constructor executes. The this
pointer passed to the constructor is the base of the stack allocation.
The second variable p
is just a local pointer, and the compiler (depending on optimizations) may store this value on the local stack or in a register.
cout << myClass.get_nmbr() << endl;
Call the get_nmbr()
method of the local myClass
instance. Again, the this
pointer points to the local stack frame allocation. This function finds the value of instance variable i
and returns it to the caller. Note that, because the object is allocated on the stack frame, i
lives on the stack frame as well.
p = &myClass;
Store the address of the myClass
instance in variable p
. This is a stack address.
cout << p;
return 0;
}
Print out the local variable p
and return.
All of your code is only concerned with stack allocations. The result of that is that when the function's scope is left/closed at execution time (e.g. the function returns), the object will be automatically "destructed" and its memory freed. If there are pointers like p
that you return from that function, you're looking at a dangling pointer, i.e. a pointer that points at an object that's freed and destructed. (The behavior of a memory access through such a dangling pointer is "undefined" as per language standard.)
If you want to allocate an object on the heap, and therefore expand its lifetime beyond the scope wherein it's declared, then you use the new operator in C++. Under the hood, new
calls malloc and then calls an appropriate constructor.
You could extend your above example to something like the following:
{
MyClass stackObj(100); // Allocate an instance of MyClass on the function's stack frame
MyClass *heapObj = new MyClass(100); // Allocate an instance of MyClass from the process heap.
printf("stack = %p heap = %p\n", stackObj, heapObj);
// Scope closes, thus call the stackObj destructor, but no need to free stackObj memory as this is done automatically when the containing function returns.
delete heapObj; // Call heapObj destructor and free the heap allocation.
}
Note: You may want to take a look at placement new, and perhaps auto pointers and shared pointers in this context.
No comments:
Post a Comment