Member values on stack or heap? - c++

This could be a duplicate. But,I couldnt find one.
Doubt:
Let us suppose class A and class B.
If I do this.
A* aPtr = new A; //This is an heap allocation
If I do this
B bObj; //This is stack allocatio
What if I have a class C, which has both A and B obj like this.
class C
{
A aObj;
B bObj;
};
and if the allocation of C is like this:
C *cptr = new C; //here memory allocation for cptr is heap.
//But, what about aObj and bObj, which are not heap allocated?
Are both aObj and bObj allocated on heap, though they look like stack objects?

I personally hate the word "heap" and "stack" when refereeing to C++ because the C++ standard does not enforce where the memory gets allocated. All the standard guarantees is when the memory will be freed.
Therefore, I prefer the names Dynamic memory allocation and Automatic memory allocation to distinguish between the two.
Automatic memory allocation will be deleted when either it goes out of scope or the object it lives in is deleted.
Dynamic memory allocation will be deleted when it is explicitly freed in the code.
Something like this C *cptr = new C; is allocated using the Dynamic memory allocation and will require to be deleted before the program ends or you will have undefined behavior.
Where as B bObj; will be allocated using the automatic memory and will be deleted when the object it lives in is deleted.

aObj and bObj are members of the C instance on the heap. So yes, cpt->aObj and cpt->bObj are on the heap.
If instead, you had
C c;
then c.aObj is on the stack and c.bObj is on the stack.

In the declaration of class C, the member A and B are just also declaration. With operator [new], the pointer cptr will be allocated in heap, and the members will also be in heap.

Related

Does my C++ variable live on the stack or the heap?

This is my first question on stack overflow. Apologies if this is a "dumb" question, but I'm currently learning C++, and I'm a little confused by something. As I understand it, in the code below, the variable "myVariable" is declared on the heap but instantiated in the constructor on the stack. So where does it "live" - on the heap or the stack?
class MyClass{
int _myVariable;
MyClass(int i){
_myVariable = i;
}
}
The member variable is allocated according to how class is instantiated.
void example() {
MyClass a{17}; // This allocates memory on stack
MyClass *b = new MyClass(17); // This allocates memory on heap
}
"Stack" and "Heap" are implementation details. The C++ standard defines Automatic Storage and Dynamic Storage.
The most common implementations for the storage of variables are stack and heap, respectively.
The new operator makes an object live on the dynamic storage:
MyClass* mc = new MyClass(14);.
Note how we now need to use a pointer to access it.
With automatic storage, we can omit the pointer semantics:
MyClass mc = MyClass(14); // constructs an object on the automatic storage.
The object lifetime is managed - you've guessed - automatically. More precisely until the end of the scope.
With dynamically allocated objects, you have to manage the lifetime of the objects yourself.
There are cases where you can't use automatic storage: Namely polymorphism.
If MyClass is polymorphic (that means, it has virtual functions), you can't put it into the automatic storage since the compiler needs to know the size of an object. Since with polymorphism, the size of the pointed-to object can change at runtime it's not possible to create it on the automatic storage.
MyClass c = MyClass2(); //Object Slicing
c.foo(); // calls MyClass::foo()
MyClass* cc = new MyClass2(); //No Object Slicing
cc->foo(); // calls MyClass2::foo();
There are helper classes that take away the responsibility to clean up your memory:
unique_ptr and shared_ptr (although the latter is used rarely).
In the given code, nothing is allocated, you have a mere class declaration.
It is contradictory (and wrong) that "myVariable" is declared on the heap while instantiated in the constructor on the stack.
A simple constructor like yours does no allocation, it just assigns value upon creation of a class instance. Constructors do not allocate the instance, destructors do not deallocate it.
The allocation being done on the heap or on the stack will depend on how you use the class (as a plain variable or with a pointer).
It depends on where does the object live. If the actual object is on the heap the variable also lives on the heap. If the object lives on the stack the variable also lives on the stack.
Look at this example:
MyClass myObject = MyClass(5); // myObject lives on the stack and thus the variable i for myObject also lives on the stack
MyClass* newObject = new MyClass(5); // newObject is allocated on the heap and the variable i for newObject lives on the heap
delete newObject; // since newObject is created using new we must free the memory after use

Class members memory allocation

My question is mostly theoretical. Suppose we have a class
class A{
private:
int * a;
int b;
private:
A(){
a = new int[100];
b = 100;
}
~A(){
delete [] a;
}
}
As far as I know if we create object of type A dynamically (A * a = new A()) the memory for this object will allocate in heap and if I use (A a) it will be created on stack (A a). In the case when object is created on stack memory for variable a will allocated on heap and in case when we allocated object on heap memory for object b will be allocated on stack. First question for me to be sure: am I right?
And second question would it be more efficient to store all members of class in heap memory or stack memory eg?
class A{
private:
int * a;
int * b;
private:
A(){
a = new int[100];
b = new int(100);
}
~A(){
delete [] a;
delete b;
}
}
When I said efficient I mean that all data about class member will be storing near each other in memory in heap or stack (actually I'm not sure that is correct that they will be storing near each other).
First off there is no heap or stack in C++. Instead we have automatic storage duration and dynamic storage duration. A object with automatic storage duration is a scoped object. When it goes out of scope it is automatically cleaned up. An object with dynamic storage duration on the other hand is not bound by its scope. Its lifetime only ends when it is explicitly ended by the program (generally this means calling delete).
Now in A you have one object stored with automatic storage duration , b, and one with dynamic storage duration ,a. This means that b will live wherever the A instance lives. a also lives within the A instance but the memory it points to will reside somewhere in memory but we do not know where. When the instance is destroyed b will automatically be cleaned up but a will required special handling in the destructor otherwise the memory will leak. You can visualize it like
A
+------+ +----------+
| a->+---| 100 ints |
| b | +----------+
+------+
As far as efficiency goes as Some programmer dude mentioned you should not really worry about that. You should use the types that you fell is right for the job. Once you have it up and running then you can profile it to find where the bottle neck is. If you see too many cache misses because of using pointers then you can look at trying to localize the data to the class itself.
I would also like to mention then if you find yourself writting some_type* name = new/new[] then you should consider using a std:unique_ptr<some_type>/std:unique_ptr<some_type[]> or std::vector<some_type>.
No, you are not exactly correct.
a and b are variables inside your object.
They both extends the size of your class - at least by the size of sizeof(int*).
Depending of the way you constructed your object, the memory for this variables is allocated on stack or heap as you already mentioned:
new A/int/etc allocates memory on heap
A/int/etc. var allocates memory on stack
The thing you miss is that your data allocated in constructor
a = new int[100];
is not a part of your class object. It is some external data. In your class object you have only a int* member (with a size of 4-8 bytes, depending on architecture) that points to this data.
First of all the downside to the member raw pointers (for ex. MyClass) is it forces to #include the header where MyClass is declared. This can lead to slow compilation. To solve you can use smart pointers with forward declarations.
And second question would it be more efficient to store all members of class in heap memory or stack memory eg?
Typically best to use pointer only when necessary. You should generally declare the members as values in class. It will be local, there will be less chance for errors, fewer allocations, ultimately fewer things that could go wrong, and the compiler can always know it is there at a specified offset so... it helps optimization and binary reduction at a few levels.

Heap vs Stack memory usage C++ for dynamically created classes

If you create a class in C++ with non-pointer member variables and non-pointer member functions yet you initialize an instance of the class dynamically (using pointers) does memory usage come from the heap or the stack?
Useful info for a project I am working on as I am trying to reduce memory from the stack :).
Any response is greatly appreciated.
Many thanks and happy coding.
If you use operator new for allocating you class, than it is put on the heap. Not matter if member variables are accessed by pointers or not.
class A {
int a;
float* p;
};
A* pa = new A(); // required memory is put on the heap
A a; // required memory is put on the stack
But be careful as not every instance accessed by a pointer may actually be located on the heap. For example:
A a; // all members are on the stack
A* pa = &a; // accessed by pointer, but the contents are still not on the heap!
On the other side a class instance located on the stack may have most of its data on the heap:
class B {
public:
std::vector<int> data; // vector uses heap storage!
B() : data(100000) {}
};
B b; // b is on the stack, but most of the memory used by it is on the heap
If you use 'new' to create an object the object is created in the heap.
for the pointer variable memory will be allocated in stack but when you are using new or malloc then that memory segment will be allocated in heap

Class members and explicit stack/heap allocation

Let's say we have 4 classes as follows:
class A
{
public:
A(void) : m_B()
{
}
private:
B m_B;
}
class B
{
public:
B(void)
{
m_i = 1;
}
private:
int m_i;
}
class C
{
public:
C(void)
{
m_D = new D();
}
~C(void)
{
delete m_D;
}
private:
D *m_D;
}
class D
{
public:
D(void)
{
m_i = 1;
}
private:
int m_i;
}
Lets say there are 4 cases:
case 1: A externally allocated on the stack, B internally allocated on the stack
A myA1;
case 2: A externally allocated on the heap, B internally allocated on the stack
A *myA2 = new A();
case 3: C externally allocated on the stack, D internally allocated on the heap
C myC1;
case 4: C externally allocated on the heap, D internally allocated on the heap
C *myC2 = new C();
What goes on in each of these cases? For example, in case 2, I understand the pointer myA2 is allocated on the stack, the A object exists in the heap, but what about the m_B attribute? I assume space on the heap allocated for it as well because it wouldn't make sense for an object to exist in heap space and then it's attribute goes out of scope. If this is true then does that mean the external heap allocation overrides the internal stack allocation?
What about case 3, myC1 is allocated on the stack, however m_D is allocated on the heap. What happens here? Are the two parts split across memory? If I removed the 'delete m_D' from the destructor and myC1 went out of scope, would there be a memory leak for the space allocated on the heap for m_D?
If there are any tutorials/articles that go over this in detail I would love a link.
I think that you are confusing "stack/heap allocation" and "automatic variable".
Automatic variables are automatically destroyed when going out of context.
Stack allocation is the fact that the memory is allocated on the execution stack. And variable allocated on the stack are automatic variables.
Also, members are automatic variables whose destructors get called when its owner is destroyed. In the case of pointers, they are destroyed but not the underlying object, you have to explicitly call delete. To make sure that the underlying object is destroyed you have to use smart or unique pointers.
To put it another way: variables/members that you have to call delete on, are not automatic variables.
Lastly, member of a class are allocated on the same memory segment of the its owner.
In you code:
A.m_B is an automatic variable. If A is on the stack so is B and if A is on the heap so is B.
B.m_i and D.m_i are an automatic variables and will be allocated on the same memory segment of their owner
The pointer C.m_D is an automatic variable, but the pointed object of type D is not, you have to explicitly call delete on the pointer to delete the underlying object. So, the pointer C.m_D is allocated on the same memory segment, but not the underlying objet. It's cleary allocated by new and will be on the heap.
So:
Case 1: Everything is on the stack and automatic (ie: destroyed automatically).
Case 2: myA2 is on the heap and not automatic (you have to delete myA2). Its member m_B2 is an automatic variable that will be destroyed when myA2 is destroyed. Also since myA2 is on the heap, m_B, like any member of a class, is in the same memory space the heap too.
Case 3: myC1 is on the stack and is an automatic variable, The pointer to m_D is on the stack too, but not the object pointed by m_D which is allocated by new on the heap.
Case 4: Same as case3 but myC2 is on the heap and is not automatic. So you have to delete myC2 (which will delete m_D).
Case 1: everything on the "stack" (automatic storage). Resources are released as you exit scope.
Case 2: myA2 is on the "heap", so is it's m_B, and you only have to worry about releasing the resources taken up by myA2. it's m_B will be destructed automatically when myA2 is.
Case 3: myC1 is on the stack, it's m_D points to a D on the heap, but the C destructor takes care of deleting it, so as myC1 goes out of scope, all dynamically allocated resources are cleared.
Case 4: myC2 dynamically allocated, to it must be deleted to release resources taken by it. Deleting it will call it's constructor which in turn will take care of it's m_D, as in case 3.
I am not sure about articles, I am sure there are plenty around. But I suggest reading some good C++ books
Your object is a piece of organised memory. Object does not allocate it's members on the stack, it just consists of it's members.
Case 2: the whole object exists in the heap, this means that all it's members lie in the heap.
Case 3: the whole object exists on the stack. The trick is that it's not D class instance who is member of myC1, but pointer-to-B is physically member of myC1. So member of myC1 lies on stack and points to some D instance that lies in the heap.

Are data members allocated in the same memory space as their objects in C++?

Say I've got a class like this:
class Test
{
int x;
SomeClass s;
}
And I instantiate it like this:
Test* t = new Test;
Is x on the stack, or the heap? What about s?
Test a;
Test *t = new Test;
a, and all its members, are on the stack.
The object pointed to by t, and all its members, are on the heap.
The pointer t is on the stack.
Each time you "instantiate" an object/symbol using a new (we are speaking C++ here), a new memory zone will be allocated for this object. If not, it will be put on the "local" memory zone.
The problem is that I have no standard definition for "local" memory zone.
An example
This means that, for example:
struct A
{
A()
{
c = new C() ;
}
B b ;
C * c ;
}
void doSomething()
{
A aa00 ;
A * aa01 = new A() ;
}
The object aa00 is allocated on the stack.
As aa00::b is allocated on a "local" memory according to aa00, aa00::b is allocated inside the memory range allocated by the new aa00 instruction. Thus, aa00::b is also allocated on stack.
But aa00::c is a pointer, allocated with new, so the object designed by aa00::c is on the heap.
Now, the tricky example: aa01 is allocated via a new, and as such, on the heap.
In that case, as aa01::b is allocated on a "local" memory according to aa01, aa01::b is allocated inside the memory range allocated by the new aa01 instruction. Thus, aa01::b is on the heap, "inside" the memory already allocated for aa01.
As aa01::c is a pointer, allocated with new, the object designed by aa01::c is on the heap, in another memory range than the one allocated for aa01.
Conclusion
So, the point of the game is:
1 - What's the "local" memory of the studied object: Stack of Heap?
2 - if the object is allocated through new, then it is outside this local memory, i.e., it is elsewhere on the heap
3 - if the object is allocated "without new", then it is inside the local memory.
4 - If the "local" memory is on the stack, then the object allocated without new is on the stack, too.
5 - If the "local" memory is on the heap, then the object allocated without new is on the heap, too, but still inside the local memory.
Sorry, I have no better vocabulary to express those concepts.
Since you've used new, it's all on the heap, stored [more or less] contiguously in t's memory area.
t is on the stack. The object at *t is on the heap. It contains an int and a SomeClass object next to each other in a unit.
Since you're using new, you're allocating your object on the heap. Consequently, every members of the Test pointed by t are on the heap too.
class MyClass {
int i;
MyInnerClass m;
MyInnerClass *p = new MyInnerClass();
}
MyClass a;
MyClass *b = new MyClass();
a is on the stack; its members a.i and a.m (including any members of a.m) and a.p (the pointer, not the object it points to) are part of it and so also on the stack.
The object pointed to by a.p is on the heap.
The object pointed to by b is on the heap, including all its members; and so is the object pointed to by b.p.