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

kbi*_*irk 26 c++ memory heap stack memory-management

假设我们有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;
}
Run Code Online (Sandbox Code Playgroud)

可以说有4种情况:

情况1:在堆栈上外部分配,B在堆栈内部分配

A myA1;
Run Code Online (Sandbox Code Playgroud)

情况2:在堆上外部分配,B内部分配在堆栈上

A *myA2 = new A();
Run Code Online (Sandbox Code Playgroud)

情况3:C在堆栈外部分配,D在堆内部分配

C myC1;
Run Code Online (Sandbox Code Playgroud)

情况4:C在堆上外部分配,D在堆内部分配

C *myC2 = new C();
Run Code Online (Sandbox Code Playgroud)

每种情况都会发生什么?例如,在第2种情况下,我理解指针myA2是在堆栈上分配的,A对象存在于堆中,但是m_B属性呢?我假设堆上的空间也是为它分配的,因为对象存在于堆空间中然后它的属性超出范围是没有意义的.如果这是真的那么这意味着外部堆分配是否会覆盖内部堆栈分配?

怎么样的情况3,myC1被分配在堆栈上,但m_D在堆上分配.这里发生了什么?两个部分是否在内存中分开?如果我从析构函数中删除了'delete m_D'并且myC1超出了范围,那么堆上为m_D分配的空间是否存在内存泄漏?

如果有任何教程/文章详细介绍,我会喜欢一个链接.

Mes*_*sop 44

我认为你混淆了"堆栈/堆分配"和"自动变量".

离开上下文时自动销毁自动变量.

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

此外,成员是自动变量,其主体在其所有者被销毁时被调用.在指针的情况下,它们被销毁但不是底层对象,您必须显式调用delete.要确保底层对象被销毁,您必须使用智能或唯一指针.

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

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

在你的代码中:

  • A.m_B是一个自动变量.如果A在堆栈上,那么是B并且A在堆上,所以是B.
  • B.m_i 和D.m_i是一个自动变量,将分配在其所有者的同一内存段上
  • 指针 C.m_D是一个自动变量,但类型d的指向对象不,你必须明确地调用delete上的指针删除底层对象.因此,指针C.m_D分配在相同的内存段上,但不是基础的objet.它是由new分配的,它将在堆上.

所以:

  • 案例1:所有东西都在堆栈上并自动(即:自动销毁).
  • 案例2: myA2在堆上而不是自动(你必须delete myA2).它的成员m_B2是一个自动变量,在被销毁时将被myA2销毁.此外,因为myA2在堆上,m_B就像类的任何成员一样,堆也在同一个内存空间中.
  • 情况3: myC1在堆栈上并且是一个自动变量,指针m_D也在堆栈上,但不是指向的对象由m_D堆上的new分配.
  • 情况4:与case3相同但是myC2在堆上并且不是自动的.所以你必须删除myC2(将删除m_D).


jua*_*nza 7

案例1:"堆栈"上的所有内容(自动存储).退出作用域时会释放资源.

案例2:myA2在"堆"上,所以它是m_B,你只需要担心释放所占用的资源myA2.它m_B会被自动销毁myA2.

情况3:myC1在堆栈上,它m_D指向D堆上的a,但是C析构函数负责删除它,因此myC1超出范围时,将清除所有动态分配的资源.

情况4:myC2动态分配,必须删除它才能释放它所占用的资源.删除它会调用它的构造函数,而构造函数又会照顾它m_D,就像在案例3中一样.

我不确定文章,我相信周围有很多.但我建议你阅读一些优秀的C++书籍