Reputation: 87
I'm starting to learn the topic of dynamic memory allocation.
I have the following code:
#include <iostream>
#include "A.h"
#include "B.h"
using namespace std;
int main() {
/* Both objects on Stack */
A classAStack;
B classBStack;
/* Both objects on Heap*/
// A *classAHeap = new A();
// B *classBHeap = new B();
/* A objects on Heap B ???*/
A *classAHeap = new A();
return 0;
}
#ifndef A_H_
#define A_H_
#include <iostream>
#include "B.h"
class A {
public:
A();
virtual ~A();
public:
B b;
};
#endif /* A_H_ */
#include "A.h"
A::A() {
std::cout <<"Constructor A called" << std::endl;
}
A::~A() {
}
#ifndef B_H_
#define B_H_
#include <iostream>
class B {
public:
B();
virtual ~B();
};
#endif /* B_H_ */
#include "B.h"
B::B() {
std::cout <<"Constructor B called" << std::endl;
}
B::~B() {
}
The output of the Debugger is:
Temporary breakpoint 6, main () at ../src/HeapStackTest02.cpp:18 18 A classAStack; Breakpoint 4, B::B (this=0x23aa58) at ../src/B.cpp:12 12 std::cout <<"Constructor B called" << std::endl; Breakpoint 5, A::A (this=0x23aa50) at ../src/A.cpp:13 13 std::cout <<"Constructor A called" << std::endl; Breakpoint 4, B::B (this=0x23aa40) at ../src/B.cpp:12 12 std::cout <<"Constructor B called" << std::endl; Breakpoint 4, B::B (this=0x60004b048) at ../src/B.cpp:12 12 std::cout <<"Constructor B called" << std::endl; Breakpoint 5, A::A (this=0x60004b040) at ../src/A.cpp:13 13 std::cout <<"Constructor A called" << std::endl; Breakpoint 1, main () at ../src/HeapStackTest02.cpp:30 30 return 0;
To my question:
Where is the member-variable b
of class A
?
If I look at the address in section 0x23a, it seems to be the stack, and the section 0x6000 seems to be the heap.
I'm working on a Windows 64-bit system.
Why the member-variable b
is also on the heap, without the new
operator being called?
Upvotes: 3
Views: 598
Reputation: 164
To answer the question, let's start with finding out how many instances of type B do we have. The answer is 3.
One instance is member b of type A (on stack). Another one is instance of B on stack, and the third one is the instance of member b of type A on heap.
Why is it on heap? It is there, because you created instance of type A on heap, and instance of A has instance of B as member.
So one of 3 instances of B is on heap, and the other 2 are on stack.
Upvotes: 3
Reputation: 385108
The member is b
is part of the object that you dynamically allocated, so it is part of that dynamic allocation and is at the same location in memory.
If the members were not part of the object, what would be left? What would you have dynamic allocated?
This is why you should avoid the terminology "on the heap" when you see new
. It is not just things that you new
that are "on the heap". No, new
dynamically allocates an object and everything that the object directly contains. Any mental association between how you wrote an object's declaration and whether it is "on the heap" or "on the stack" is doomed to failure.
The only reliable way to determine an object's storage duration is to know its history; the only reliable way to determine an object's storage location is to not bother because you don't need to.
Upvotes: 4
Reputation: 217
Consider this:
#include <iostream>
#include <string>
class B {
public:
int64_t x = 42;
int64_t y = 7;
};
class A1 {
public:
B b;
};
class A2 {
public:
A2() { b = new B(); }
B* b;
~A2() { delete b; }
};
int main() {
std::cout << sizeof(A1) << std::endl; // prints 16
std::cout << sizeof(A2) << std::endl; // prints 8
// Section (2)
A1 a1; // Instance of A1 and B are on the stack
A2 a2; // Instance of A2 is on the stack. B is on the heap.
A1* a3 = new A1();
std::cout << a3 == &(a3->b) << std:: endl; // prints true
A2* a4 = new A2();
std::cout << a4 == a4->b << std::endl; // prints false
return 0;
}
Upvotes: 1