类成员和显式堆栈/堆分配
假设我们有4个类,如下所示:
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;
}
可以说有4种情况:
情况1:从外部分配到堆栈上,B在堆栈内部分配
A myA1;
情况2:在堆外部分配一个内部分配的B
A *myA2 = new A();
情况3:C在堆栈外部分配,D在堆内部分配
C myC1;
情况4:C在堆外部分配,D在堆内部分配
C *myC2 = new C();
每种情况下都会发生什么? 例如,在情况2中,我明白指针myA2在堆栈上分配,A对象存在于堆中,但m_B属性又如何? 我也为堆分配了空间,因为在堆空间中存在对象是没有意义的,然后它的属性超出了范围。 如果这是真的,那么这是否意味着外部堆分配会覆盖内部堆栈分配?
情况3,myC1分配在堆栈上,但是m_D分配在堆上。 这里发生了什么? 这两个部分是分裂的吗? 如果我从析构函数中删除了'delete m_D',并且myC1超出了范围,那么堆中为m_D分配的空间是否会发生内存泄漏?
如果有任何教程/文章详细讨论这一点,我会喜欢一个链接。
我认为你很困惑“堆栈/堆分配”和“自动变量”。
自动变量在退出上下文时会自动销毁。
堆栈分配是内存分配在执行堆栈上的事实。 分配给堆栈的变量是自动变量。
另外, 成员是自动变量 ,当其所有者被销毁时,析构函数会被调用。 在指针的情况下,它们被销毁但不是底层对象,你必须明确地调用delete。 为了确保底层对象被销毁,你必须使用智能指针或唯一指针。
换句话说:你必须调用delete的变量/成员不是自动变量。
最后,一个类的成员被分配在它的所有者的同一个内存段上。
在你的代码中:
A.m_B
是一个自动变量。 如果A在堆栈上,那么B在A上,而A在堆上,B也是如此。 B.m_i
和D.m_i是一个自动变量,将被分配到它们所有者的同一个内存段中 C.m_D
是一个自动变量,但是类型D的指向对象不是,您必须显式调用指针上的delete来删除底层对象。 所以,指针C.m_D被分配在同一个内存段上,但不是底层对象。 它是由新的cleary分配,并将在堆上。 所以:
myA2
在堆上,而不是自动的(你必须delete myA2
)。 它的成员m_B2
是一个自动变量,当myA2
被销毁时myA2
被销毁。 另外,由于myA2
在堆上, m_B
与类中的任何成员一样,也在同一个内存空间中。 myC1
在堆栈上并且是一个自动变量,指向m_D
的指针m_D
堆栈中,但不是由m_D
新分配的m_D
指向的对象。 myC2
在堆上并且不是自动的。 所以你必须删除myC2
(它会删除m_D
)。 案例1:“堆栈”(自动存储)中的所有内容。 资源在您退出范围时被释放。
情况2: myA2
在“堆”上,它也是m_B
,你只需要担心释放myA2
的资源。 它的m_B
会在myA2
被自动破坏。
情况3: myC1
在堆栈上,它的m_D
指向堆上的一个D
,但C
析构函数负责删除它,因此当myC1
超出范围时,将清除所有动态分配的资源。
情况4: myC2
动态分配,必须删除它才能释放它所占用的资源。 删除它会调用它的构造函数,而这个构造函数反过来会处理它的m_D
,就像情况3一样。
我不确定文章,我相信周围有很多。 但我建议阅读一些很好的C ++书籍
你的对象是一块有组织的内存。 对象不会在堆栈上分配它的成员,它只包含它的成员。
情况2:整个对象存在于堆中,这意味着它的所有成员都躺在堆中。
情况3:整个对象存在于堆栈上。 诀窍是它不是D
类实例是myC1
成员,但指向B的实体是myC1
成员。 所以myC1
成员位于栈上并指向位于堆中的某个D
实例。