Class members memory allocation - c++

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.

Related

Memory managment C++ when return from function

I just start learning C++ and have some question related to memory managment.
I will write only part today because i have many question and hope i understand it with your help.
Suppose i have class A:
typedef ... DATA;
Class A{
public:
...(contructor, destructor);
DATA foo(){
create DATA;
}
}
Now suppose i want return DATA to outer scope.
My questions are:
1.how create DATA inside function foo in better way? (examples of foo body)
a)
DATA a;
....action with a;
return a;
Questions of this way:
1.1 what does it mean DATA a;?
different source - different answers:
1.1 a) Object "a" was created on stack
My understanding: it means it was craeted not in heap but somewhere in memory what have quick access to resource and have LIFO structure, it local as it created in this function's stack frame and will be destroyed when programm goes out of function scope (frame).
1.1 b) Object "a" was created in automatic memory
My understanding: Its not a stack, but will be destroyed like in case with stack.
Who are right or, where object "a" was created? What will be if DATA is std::container (e.g vector<>),
as i understand vector<> use dinamic allocation of memory (implicitly use of new operator and it means - on heap?)? Will vector be created on heap, and will it be destroyed automaticly like in case of on stack (or in automatic memory) and i could not warried to destroy "a" and dellocate memory? If so - in case of std::containers the difference between DATA a; and DATA* ptr = new DATA();is only who responsible for -destroy and dellocate - me or auto?
1.2 How "a" will be returned?
I heard compiller knows what in case of returning local var by value coppy constructor will create a coppy place it on stack and calling scope will take it from there. In case of huge object i should use move semantic. For ex. in calling scope:
A a;
DATA b = a.foo();
Is it mean to not to coppy huge object i should define move
operator=(&& DATA)?
What if DATA just struct (huge struct), but not a class?
What should i do if DATA is std::container ?
Lots of good questions, here's some quick answers, really you should be reading a C++ text book.
1)
DATA a;
Both answers are right because they mean the same thing. Automatic storage is the technically correct term, but in practise every compiler uses a stack for automatic storage. Whatever term you use a will be destroyed when it goes out of scope.
2)
vector<DATA> v;
There's a vital thing to understand here. The vector contents (the DATA objects) are created on the heap, but the vector itself is created on the stack. This means that just like DATA a; v will be destroyed when it goes out of scope. At that point all the dynamically allocated memory will be freed and so all the DATA objects will be destroyed as well.

Where are pointers in C++ stored, on the stack or in the heap?

I am trying to understand the difference between the stack and heap memory, and this question on SO as well as this explanation did a pretty good job explaining the basics.
In the second explanation however, I came across an example to which I have a specific question, the example is this:
It is explained that the object m is allocated on the heap, I am just wondering if this is the full story. According to my understanding, the object itself indeed is allocated on the heap as the new keyword has been used for its instantiation.
However, isn't it that the pointer to object m is on the same time allocated on the stack? Otherwise, how would the object itself, which of course is sitting in the heap be accessed. I feel like for the sake of completeness, this should have been mentioned in this tutorial, leaving it out causes a bit of confusion to me, so I hope someone can clear this up and tell me that I am right with my understanding that this example should have basically two statements that would have to say:
1. a pointer to object m has been allocated on the stack
2. the object m itself (so the data that it carries, as well as access to its methods) has been allocated on the heap
Your understanding may be correct, but the statements are wrong:
A pointer to object m has been allocated on the stack.
m is the pointer. It is on the stack. Perhaps you meant pointer to a Member object.
The object m itself (the data that it carries, as well as access to its methods) has been allocated on the heap.
Correct would be to say the object pointed by m is created on the heap
In general, any function/method local object and function parameters are created on the stack. Since m is a function local object, it is on the stack, but the object pointed to by m is on the heap.
"stack" and "heap" are general programming jargon. In particular , no storage is required to be managed internally via a stack or a heap data structure.
C++ has the following storage classes
static
automatic
dynamic
thread
Roughly, dynamic corresponds to "heap", and automatic corresponds to "stack".
Moving onto your question: a pointer can be created in any of these four storage classes; and objects being pointed to can also be in any of these storage classes. Some examples:
void func()
{
int *p = new int; // automatic pointer to dynamic object
int q; // automatic object
int *r = &q; // automatic pointer to automatic object
static int *s = p; // static pointer to dynamic object
static int *s = r; // static pointer to automatic object (bad idea)
thread_local int **t = &s; // thread pointer to static object
}
Named variables declared with no specifier are automatic if within a function, or static otherwise.
When you declare a variable in a function, it always goes on the stack. So your variable Member* m is created on the stack. Note that by itself, m is just a pointer; it doesn't point to anything. You can use it to point to an object on either the stack or heap, or to nothing at all.
Declaring a variable in a class or struct is different -- those go where ever the class or struct is instantiated.
To create something on the heap, you use new or std::malloc (or their variants). In your example, you create an object on the heap using new and assign its address to m. Objects on the heap need to be released to avoid memory leaks. If allocated using new, you need to use delete; if allocated using std::malloc, you need to use std::free. The better approach is usually to use a "smart pointer", which is an object that holds a pointer and has a destructor that releases it.
Yes, the pointer is allocated on the stack but the object that pointer points to is allocated on the heap. You're correct.
However, isn't it that the pointer to object m is on the same time
allocated on the stack?
I suppose you meant the Member object. The pointer is allocated on the stack and will last there for the entire duration of the function (or its scope). After that, the code might still work:
#include <iostream>
using namespace std;
struct Object {
int somedata;
};
Object** globalPtrToPtr; // This is into another area called
// "data segment", could be heap or stack
void function() {
Object* pointerOnTheStack = new Object;
globalPtrToPtr = &pointerOnTheStack;
cout << "*globalPtrToPtr = " << *globalPtrToPtr << endl;
} // pointerOnTheStack is NO LONGER valid after the function exits
int main() {
// This can give an access violation,
// a different value after the pointer destruction
// or even the same value as before, randomly - Undefined Behavior
cout << "*globalPtrToPtr = " << *globalPtrToPtr << endl;
return 0;
}
http://ideone.com/BwUVgm
The above code stores the address of a pointer residing on the stack (and leaks memory too because it doesn't free Object's allocated memory with delete).
Since after exiting the function the pointer is "destroyed" (i.e. its memory can be used for whatever pleases the program), you can no longer safely access it.
The above program can either: run properly, crash or give you a different result. Accessing freed or deallocated memory is called undefined behavior.

Object creation on the stack/heap?

The following code creates an object on the stack:
Object o;
When creating an object on the heap we can use:
Object* o;
o = new Object();
rather than:
Object* o = new Object();
When we split the heap object-creation over two lines and call the constructor on the second line (o = new object()), does this mean in the first line (Object* o) the pointer was created on the stack? So Object o puts the object on the stack, whereas Object* o puts the pointer to a future object on the stack?
My second question involves if the two lines of code were called outside of a class. I recently read (Global memory management in C in stack or heap?) that global variables are not contained on the stack/heap but actually another part of memory? If this is the case, would Object* o create a pointer which would sit in this other part of the memory and it points to the heap object?
Actually, neither statement says anything about heap or stack. The code
Object o;
creates one of the following, depending on its context:
a local variable with automatic storage,
a static variable at namespace or file scope,
a member variable that designates the subobject of another object.
This means that the storage location is determined by the context in which the object is defined. In addition, the C++ standard does not talk about stack vs heap storage. Instead, it talks about storage duration, which can be either automatic, dynamic, static or thread-local. However, most implementations implement automatic storage via the call stack, and dynamic storage via the heap.
Local variables, which have automatic storage, are thus created on the stack. Static (and thread-local) objects are generally allocated in their own memory regions, neither on the stack nor on the heap. And member variables are allocated wherever the object they belong to is allocated. They have their containing object’s storage duration.
To illustrate this with an example:
struct Foo {
Object o;
};
Foo foo;
int main() {
Foo f;
Foo* p = new Foo;
Foo* pf = &f;
}
Now where is the object Foo::o (that is, the subobject o of an object of class Foo) created? It depends:
foo.o has static storage because foo has static storage, and therefore lives neither on the stack nor on the heap.
f.o has automatic storage since f has automatic storage (= it lives on the stack).
p->o has dynamic storage since *p has dynamic storage (= it lives on the heap).
pf->o is the same object as f.o because pf points to f.
In fact, both p and pf in the above have automatic storage. A pointer’s storage is indistinguishable from any other object’s, it is determined by context. Furthermore, the initialising expression has no effect on the pointer storage.
The pointee (= what the pointer points to) is a completely different matter, and could refer to any kind of storage: *p is dynamic, whereas *pf is automatic.
C++ offers three different ways to create objects:
Stack-based such as temporary objects
Heap-based by using new
Static memory allocation such as global variables and namespace-scope objects
Consider your case,
Object* o;
o = new Object();
and:
Object* o = new Object();
Both forms are the same. This means that a pointer variable o is created on the stack (assume your variables does not belong to the 3 category above) and it points to a memory in the heap, which contains the object.
C++ has Automatic variables - not Stack variables.
Automatic variable means that C++ compiler handles memory allocation / free by itself. C++ can automatically handle objects of any class - no matter whether it has dynamically allocated members or not. It's achieved by strong guarantee of C++ that object's destructor will be called automatically when execution is going out of scope where automatic variable was declared. Inside of a C++ object can be a lot of dynamic allocations with new in constructor, and when such an object is declared as an automatic variable - all dynamic allocations will be performed, and freed then in destructor.
Stack variables in C can't be dynamically allocated. Stack in C can store pointers, or fixed arrays or structs - all of fixed size, and these things are being allocated in memory in linear order. When a C program frees a stack variable - it just moves stack pointer back and nothing more.
Even though C++ programs can use Stack memory segment for storing primitive types, function's args, or other, - it's all decided by C++ compiler, not by program developer. Thus, it is conceptually wrong to equal C++ automatic variables and C stack variables.
The two forms are the same with one exception: temporarily, the new (Object *) has an undefined value when the creation and assignment are separate. The compiler may combine them back together, since the undefined pointer is not particularly useful. This does not relate to global variables (unless the declaration is global, in which case it's still true for both forms).
In both your examples, local variables of Object* type are allocated on the stack. The compiler is free to produce the same code from both snippets if there is no way for your program to detect a difference.
The memory area for global variables is the same as the memory area for static variables - it's neither on the stack nor on the heap. You can place variables in that area by declaring them static inside the function. The consequence of doing so is that the instance becomes shared among concurrent invocations of your function, so you need to carefully consider synchronization when you use statics.
Here is a link to a discussion of the memory layout of a running C program.
A)
Object* o;
o = new Object();
``
B)
Object* o = new Object();
I think A and B has no difference. In both the cases o is a pointer to class Object. statement new Object() creates an object of class Object from heap memory. Assignment statement assigns the address of allocated memory to pointer o.
One thing I would like to mention that size of allocated memory from heap is always the sizeof(Object) not sizeof(Object) + sizeof(void *).
Object* o;
o = new Object();
Object* o = new Object();
Both these statement creates the object in the heap memory since you are creating the object using "new".
To be able to make the object creation happen in the stack, you need to follow this:
Object o;
Object *p = &o;

Are member variables of an object that is on the heap also automatically on the heap?

class A
{
public:
A();
~A();
int X;
};
A::A()
{
X = 5;
int Y = 4;
}
//..... in another file
A * objectOnHeap = new A();
In this case, since "objectOnHeap" is on the heap, is X also on the heap even though it wasn't specifically new'd up? And in this case Y is allocated on the stack (and of course goes out of scope), correct?
I am wondering if I have gotten my wires crossed when trying to envision how objects are stored in memory.
Yes. It's on the heap. Basically, the space allocated to an object on the heap is big enough to hold all its member variables.
Yes, it's on the heap.
Some details:
When you use the "new" operator, what happens is that the compiler allocates enough space on the heap for the class, including all the space needed for all the member variables (which might also be classes, in which case their size needs to be computed too, etc.).
After this, the constructor is called on the data member classes, then on the class itself.
Whenever you don't specifically allocate memory on the heap (usually by using the new operator, or calling a function that does that for you), the memory is allocated on the stack, like the variable y in your example.
I guess half of your question remained unanswered: you were asking if Y is still allocated on the stack, that's correct indeed.
Y is on stack since is created locally;
X is on 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.