Reputation: 21126
Take the following:
A a;
class B; // No content for brevity
class A
{
public:
A()
{
b.SetTitle("hi");
}
private:
B b;
}
int main()
{
return 0;
}
The question here is if b
which is declared inside A
is declared on the heap or on the stack.
If on the heap, does this mean it is automatically deleted or must i also delete this too?
Side question:
This is what i was originally doing but thought i was being a bit stupid as i had to keep declaring everything as new everywhere.. if the above is on the stack, i guess it wasn't so stupid right?
A a;
class B; // No content for brevity
class A
{
public:
A()
{
this->b( new B() ); // I don't have C++ 14 :( so i can't do make_unique
b->SetTitle("hi");
}
private:
unique_ptr<B> b;
}
int main()
{
return 0;
}
Upvotes: 7
Views: 215
Reputation: 7905
Code Examples: Stack Vs Heap.
// Not a proper class but used for demonstration purposes
class SomeClass {
private:
int x;
int* ptr;
public:
SomeClass() {
// Both On x and ptr are on the stack when this constructor is defined and used.
x = 10;
ptr = &x;
}
SomeClass() {
// x is on the stack but ptr is on the heap and delete needs to be called to release the memory.
x = 10;
ptr = new int;
}
};
void someOtherFunction() {
SomeClass a; // on the stack relative to this function
SomeClass* ptr = nullptr; // ptr is on the stack and is initialize to null.
ptr = &a; // Still on the stack and ptr stores the address of (a).
ptr = new SomeClass(); // Now ptr lives on the heap and delete needs to be called to release its memory.
}
Initially (ptr) does not have an address stored within in it because we initialized it to nullptr upon declaring it. It is stored on the stack, the address of (ptr) at this time has an address that is part of the stack memory addressing. Now we assign the address of (a) to (ptr); (ptr) is still on the stack, (a) is on the stack and the address of (a) is stored into (ptr).
Once we set (ptr) = new SomeClass() it is at this point that the compiler sets aside memory with the size of this class object and saves a random address from the heap into (ptr). (ptr) itself is still on the stack of this function but the memory address that (ptr) now stores is from the heap. The contents of (ptr) is accessible outside the scope of this function but needs to be return either through this functions return type or one of its parameters by reference.
Another words the address of (ptr) does not change within this function, it remains the same because the variable (ptr) itself still lives on the stack, it is what this pointer variable holds that changes from a stack memory address to a heap memory address once new is used.
To demonstrate this run this code in main() and look at the results; this still applies within other functions and class-struct objects.
#include <iostream>
int main() {
int a = 10;
int* ptr = nullptr;
std::cout << "Memory Address that ptr is pointing to: " << ptr << std::endl;
std::cout << "Memory Address of ptr: " << &ptr << std::endl;
// std::cout << "What is stored in the variable at this memory address: " << *ptr << std::endl; // This can not be called program will crash,
// ptr can not be dereferenced for it is not pointing to anything
std::cout << std::endl;
ptr = &a;
std::cout << "Memory Address that ptr is pointing to: " << ptr << std::endl;
std::cout << "Memory Address of ptr: " << &ptr << std::endl;
std::cout << "What is stored in the variable at this memory address: " << *ptr << std::endl;
std::cout << std::endl;
ptr = new int;
*ptr = 12;
std::cout << "Memory Address that ptr is pointing to: " << ptr << std::endl;
std::cout << "Memory Address of ptr: " << &ptr << std::endl;
std::cout << "What is stored in the variable at this memory address: " << *ptr << std::endl;
std::cout << std::endl;
delete ptr;
return 0;
}
As you can see the memory address of (ptr) does not change, what does change is the memory address that is stored within (ptr). Now the address of (ptr) can change if you use new on another pointer that is pointing to (ptr).
Now when you call new on a class type and you store the heap memory address into a pointer of that type, the memory address is where the class object lives so in this case anything that belongs to this class is on the heap.
Globals & Static Variables:
Globals - Globals are listed in the (program file namespace)* and are accessible anywhere in the file they are declared and have the life time of the application.
Static local variables are like global variables except they are only accessible in the function they are declared and are only initialized once per application runtime. They have the life time of the application.
Static member variables to a class behave similar as regular static variables but they do not have the (this) pointer associated to them. They are visible to the function that declares them, they are initialized once per application runtime, and they have the life time of either the application run time or until there exists no more instances of that class object.
(*) Do not know the technical name but using program file namespace makes sense according to how global variables and their memory behave. - I rarely use global variables!
Here are some links for references.
Upvotes: 0
Reputation: 1986
It still could be either or even (as Thomas Matthews points out below) in a fixed memory block. In this case you can think of it as "inside of A". If you put A on the heap it's on the heap. If you allocate "A" at the top of a function, say, it's on the stack (but inside of A).
Written like this it is a part of A and its lifetime is tied to A. You only need to worry about managing A.
Upvotes: 10