C++ 类成员和显式堆栈/堆分配
假设我们有4个类,如下所示: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
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在堆栈上,那么B也是;如果A在堆上,那么B也是A.m_B
和D.m_i是一个自动变量,将分配在其所有者的同一内存段上B.m_i
- 指针
是一个自动变量,但类型为D的指针对象不是,您必须显式调用指针上的delete来删除基础对象。因此,指针C.m_D分配在同一内存段上,而不是底层对象上。它是由new分配的,并且将在堆上C.m_D
- 案例1:所有内容都在堆栈上并且是自动的(即:自动销毁)
- 案例2:
在堆中,并且不是自动的(您必须myA2
)。其成员删除myA2
是一个自动变量,当m_B2
被销毁时,该变量将被销毁。另外,由于myA2
位于堆上,myA2
与类的任何成员一样,也位于堆的相同内存空间中mub
- 案例3:
在堆栈上,是一个自动变量,指向myC1
的指针也在堆栈上,但不是由堆上的new分配的m\u D
指向的对象m\u D
- 案例4:与案例3相同,但
在堆上,并且不是自动的。因此,您必须删除myC2
(这将删除myC2
)mud