类成员和显式堆栈/堆分配 [英] Class members and explicit stack/heap allocation

查看:115
本文介绍了类成员和显式堆栈/堆分配的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们假设我们有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种情况:



case 1:A在堆栈上外部分配,B在堆栈内部分配

  A myA1; 

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

  A * myA2 = new A(); 

case 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的空间会有内存泄漏吗?



如果有任何教程/文章,详细这一点我会喜欢一个链接。

解决方案

我认为你是混淆堆栈/堆分配和自动变量。

$ b $



自动变量会在上下文时自动销毁。是内存分配在执行堆栈上的事实。



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



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



最后,类的成员分配在它的所有者的同一内存段。



在您的代码中:




  • A.m_B 是一个自动变量。如果A在堆栈上,那么是B,并且A在堆上,所以是B.

  • B.m_i 和D. m_i是自动变量,将分配在所有者的同一内存段上

  • 指针 C.m_D 是一个自动变量,但是D类型的指向对象不是,你必须显式调用delete上的指针来删除底层对象。因此,指针C.m_D被分配在相同的存储器段上,但不是基础对象。



所以:




  • 情况1:一切都在堆栈上,并自动(即:自动销毁)。

  • myA2 位于堆上,而不是自动(您必须删除myA2 )。它的成员 m_B2 是一个自动变量,当 myA2 被销毁时会被销毁。另外,由于 myA2 在堆上,与类的任何成员一样, m_B 在同一内存空间
  • c> 到 m_D 也在堆栈上,但不是由在堆上由new分配的 m_D 指向的对象。 因此您必须删除 myC2 (将删除 m_D )。

Let's say we have 4 classes as follows:

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;
}

Lets say there are 4 cases:

case 1: A externally allocated on the stack, B internally allocated on the stack

A myA1;

case 2: A externally allocated on the heap, B internally allocated on the stack

A *myA2 = new A();

case 3: C externally allocated on the stack, D internally allocated on the heap

C myC1;

case 4: C externally allocated on the heap, D internally allocated on the heap

C *myC2 = new C();

What goes on in each of these cases? For example, in case 2, I understand the pointer myA2 is allocated on the stack, the A object exists in the heap, but what about the m_B attribute? I assume space on the heap allocated for it as well because it wouldn't make sense for an object to exist in heap space and then it's attribute goes out of scope. If this is true then does that mean the external heap allocation overrides the internal stack allocation?

What about case 3, myC1 is allocated on the stack, however m_D is allocated on the heap. What happens here? Are the two parts split across memory? If I removed the 'delete m_D' from the destructor and myC1 went out of scope, would there be a memory leak for the space allocated on the heap for m_D?

If there are any tutorials/articles that go over this in detail I would love a link.

解决方案

I think that you are confusing "stack/heap allocation" and "automatic variable".

Automatic variables are automatically destroyed when going out of context.

Stack allocation is the fact that the memory is allocated on the execution stack. And variable allocated on the stack are automatic variables.

Also, members are automatic variables whose destructors get called when its owner is destroyed. In the case of pointers, they are destroyed but not the underlying object, you have to explicitly call delete. To make sure that the underlying object is destroyed you have to use smart or unique pointers.

To put it another way: variables/members that you have to call delete on, are not automatic variables.

Lastly, member of a class are allocated on the same memory segment of the its owner.

In you code:

  • A.m_B is an automatic variable. If A is on the stack so is B and is A is on the heap so is B.
  • B.m_i and D.m_i are an automatic variables and will be allocated on the same memory segment of their owner
  • The pointer C.m_D is an automatic variable, but the pointed object of type D is not, you have to explicitly call delete on the pointer to delete the underlying object. So, the pointer C.m_D is allocated on the same memory segment, but not the underlying objet. It's cleary allocated by new and will be on the heap.

So:

  • Case 1: Everything is on the stack and automatic (ie: destroyed automatically).
  • Case 2: myA2 is on the heap and not automatic (you have to delete myA2). Its member m_B2 is an automatic variable that will be destroyed when myA2 is destroyed. Also since myA2 is on the heap, m_B, like any member of a class, is in the same memory space the heap too.
  • Case 3: myC1 is on the stack and is an automatic variable, The pointer to m_D is on the stack too, but not the object pointed by m_D which is allocated by new on the heap.
  • Case 4: Same as case3 but myC2 is on the heap and is not automatic. So you have to delete myC2 (which will delete m_D).

这篇关于类成员和显式堆栈/堆分配的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆