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
Related
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.
If I declare a struct such as this one:
struct MyStruct
{
int* nums;
};
MyStruct ms;
ms.nums = new int[4];
Do I need to call delete ms.nums; before exiting my program or will the member variable nums automatically get deallocated because the MyStruct instance ms wasn't declared on the heap?
Yes, you have to delete that.. struct's default destructor won't do that. It will just delete the pointer variable which holds the address of the object and object will be left alone forever.
Better to do the deletion inside the struct's destructor
struct MyStruct
{
int* nums;
public :
~MyStruct()
{
if(nums != NULL)
delete nums;
}
};
The member variable nums (which is a pointer) will get automatically deallocated when ms, the struct containing it, is popped off the stack.
However, the memory pointed to by nums will NOT. You should call delete [] ms.nums; before your program exits.
You always have to call delete to deallocate all the memory that you explicitly allocated using new.
When you allocate memory using new, memory is allocated in heap and the base address of the block is returned back.
Your struct is present in stack which contains a pointer pointing to that base address. When the struct object leaves the scope, the object is deallocated , i.e. the pointer containig the address of allocated heap memory block is gone, but the heap memory itself is still allocated which you can't deallocate now.
You need to call delete if memory allocated and pointer returned to num. Here num is a pointer inside a structure. Memory for num is allocated when you declare structure variable. But memory address which is allocated by new should be un-allocated by calling delete
Memory for the pointer itself will be deallocated when the object is destroyed, as it is for any class member. However, the array it points to won't be deleted - there is no way to know what the pointer points to, whether it was allocated by new or new[] or not dynamically allocated at all, or whether anything else still wants to use it. To avoid memory leaks, you should delete it, with the array form delete [] ms.nums;, once you've finished with it.
Since it's often hard to do this correctly, why not use a library class to manage the array correctly for you?
#include <vector>
struct MyStruct
{
std::vector<int> nums;
};
MyStruct ms;
ms.nums.resize(4);
Now all the memory will be released automatically when ms is destroyed; and the class is correctly copyable and (since C++11) efficiently movable.
The struct is allocated on the stack, which basically is a pointer to an Array. the array is allocated on the heap. Every time you write "new" that means that the allocation is on the heap therefore you need to "delete" it. On the other hand the struct will be remove as soon as you exit the function.
When program exit, OS will free all memory allocated by your program.
On the other hand, if a memory allocation occurs multiple times during the life of the program, then surely it should be released to prevent dangling pointers.
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.
This is an allocation on the stack:
char inStack[10];
// and
MyStruct cl;
And this should be allocated in the heap:
char* inHeap = new char[10];
// and
MyClass cl = new MyClass();
What if MyClass contains a char test[10] variable? Does this:
MyClass cl = new MyClass()
...mean that the 10 byte long content of MyClass::test is allocated in the heap instead of the stack?
It would be allocated inside the object, so that if the object is on the heap, the array will be on the heap; if the object is on the stack, the array will be on the stack; if the object is in static memory in the executable, the array will be there also.
In C++, members of objects are part of the object itself. If you have the address of the object and it's size, you know that all the members of the class will be somewhere within the range [address, address + size), no matter where in memory that address actually is (heap, stack, etc).
If MyClass has a char test[10] member, it will be allocated the same way the instance of MyClass was allocated.
MyClass mc; //mc.test is on the stack
MyClass * mcp = new MyClass; //mcp->test is on the heap
The proper terms in the language are automatic and dynamic storage, and these make a bit more sense than stack and heap. In particular automatic storage does not imply stack in general, only in local variables in functions, but as you mention, if you are defining a member of a class, automatic storage will be wherever the enclosing object is, which can be the stack, the heap or a static object.
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.