类成员和显式堆栈/堆分配

假设我们有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分配,并将在堆上。
  • 所以:

  • 案例1:一切都在堆栈上并自动(即:自动销毁)。
  • 情况2: myA2在堆上,而不是自动的(你必须delete myA2 )。 它的成员m_B2是一个自动变量,当myA2被销毁时myA2被销毁。 另外,由于myA2在堆上, m_B与类中的任何成员一样,也在同一个内存空间中。
  • 情况3: myC1在堆栈上并且是一个自动变量,指向m_D的指针m_D堆栈中,但不是由m_D新分配的m_D指向的对象。
  • 情况4:情况3相同,但是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实例。

    链接地址: http://www.djcxy.com/p/2353.html

    上一篇: Class members and explicit stack/heap allocation

    下一篇: Could not reserve enough space for object heap