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

C++ 类成员和显式堆栈/堆分配,c++,memory,memory-management,stack,heap,C++,Memory,Memory Management,Stack,Heap,假设我们有4个类,如下所示: class A { public: A(void) : m_B() { } private: B m_B; } class B { public: B(void) { m_i = 1; } private: int m_i; } clas

假设我们有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:A在堆栈上外部分配,B在堆栈上内部分配

A myA1;
A *myA2 = new A();
案例2:A在堆上外部分配,B在堆栈上内部分配

A myA1;
A *myA2 = new A();
案例3:C在堆栈上外部分配,D在堆上内部分配

C myC1;
C *myC2 = new C();
案例4:C在堆上外部分配,D在堆上内部分配

C myC1;
C *myC2 = new C();
每种情况都会发生什么?例如,在案例2中,我知道指针myA2分配在堆栈上,A对象存在于堆中,但是m_B属性呢?我假设堆上也为它分配了空间,因为对象存在于堆空间中是没有意义的,然后它的属性就超出了范围。如果这是真的,那么这是否意味着外部堆分配会覆盖内部堆栈分配

那么案例3呢,myC1是在堆栈上分配的,而m_D是在堆上分配的。这里发生了什么?这两部分在内存中分开了吗?如果我从析构函数中删除了'delete m_D',并且myC1超出了作用域,那么堆上为m_D分配的空间是否会出现内存泄漏

如果有任何教程/文章详细介绍了这一点,我希望有一个链接

案例1:“堆栈”上的所有内容(自动存储)。资源在您退出作用域时释放

案例2:
myA2
在“堆”上,所以它是
m_B
,您只需担心释放
myA2
占用的资源。它的
m_B
将在启用
myA2
时自动销毁

案例3:
myC1
在堆栈上,它的
mud
指向堆上的
D
,但是
C
析构函数负责删除它,因此
myC1
超出范围,所有动态分配的资源都被清除

案例4:
myC2
动态分配,必须删除它才能释放它占用的资源。删除它将调用它的构造函数,而构造函数又会处理它的
mud
,如案例3所示


我对文章不太确定,我肯定有很多。但是我建议你读一些东西,你的物体是一段有组织的记忆。对象不在堆栈上分配其成员,它只是由其成员组成

案例2:整个对象存在于堆中,这意味着它的所有成员都位于堆中


案例3:整个对象存在于堆栈上。技巧在于,不是
D
类实例是
myC1
的成员,而是指向B的指针是
myC1
的物理成员。因此,
myC1
的成员位于堆栈上,并指向位于堆中的某个
D
实例。

我认为您混淆了“堆栈/堆分配”和“自动变量”

自动变量在脱离上下文时自动销毁

堆栈分配是在执行堆栈上分配内存的事实。在堆栈上分配的变量是自动变量

另外,成员是自动变量,当其所有者被销毁时,将调用其析构函数。在指针的情况下,它们被销毁,但不是底层对象,因此必须显式调用delete。要确保基础对象被销毁,必须使用智能指针或唯一指针

换句话说:必须调用delete的变量/成员不是自动变量

最后,类的成员被分配到其所有者的同一内存段上

在您的代码中:

  • A.m_B
    是一个自动变量。如果A在堆栈上,那么B也是;如果A在堆上,那么B也是
  • B.m_i
    和D.m_i是一个自动变量,将分配在其所有者的同一内存段上
  • 指针
    C.m_D
    是一个自动变量,但类型为D的指针对象不是,您必须显式调用指针上的delete来删除基础对象。因此,指针C.m_D分配在同一内存段上,而不是底层对象上。它是由new分配的,并且将在堆上
因此:

  • 案例1:所有内容都在堆栈上并且是自动的(即:自动销毁)
  • 案例2:
    myA2
    在堆中,并且不是自动的(您必须
    删除myA2
    )。其成员
    m_B2
    是一个自动变量,当
    myA2
    被销毁时,该变量将被销毁。另外,由于
    myA2
    位于堆上,
    mub
    与类的任何成员一样,也位于堆的相同内存空间中
  • 案例3:
    myC1
    在堆栈上,是一个自动变量,指向
    m\u D
    的指针也在堆栈上,但不是由堆上的new分配的
    m\u D
    指向的对象
  • 案例4:与案例3相同,但
    myC2
    在堆上,并且不是自动的。因此,您必须删除
    myC2
    (这将删除
    mud