C++ 类成员内存分配

C++ 类成员内存分配,c++,memory,memory-management,dynamic-memory-allocation,C++,Memory,Memory Management,Dynamic Memory Allocation,我的问题主要是理论性的。假设我们有一节课 class A{ private: int * a; int b; private: A(){ a = new int[100]; b = 100; } ~A(){ delete [] a; } } 据我所知,如果我们动态创建A类型的对象(A*A=newA()),该对象的内存将在堆中分配,如果我使用(A),它将在堆栈(A)上创建。在为变量a在堆栈内存上创建对象时,将在堆上

我的问题主要是理论性的。假设我们有一节课

class A{
private:
    int * a;
    int b;
private:
    A(){
      a = new int[100];
      b = 100;
    }
   ~A(){
      delete [] a;
    }
}
据我所知,如果我们动态创建A类型的对象(
A*A=newA()
),该对象的内存将在堆中分配,如果我使用(
A
),它将在堆栈
(A)
上创建。在为变量
a
在堆栈内存上创建对象时,将在堆上分配;在为对象
b
在堆上分配对象时,将在堆栈上分配内存。我要确定的第一个问题是:我说得对吗

第二个问题是,将类的所有成员存储在堆内存或堆栈内存中会更有效吗

class A{
    private:
        int * a;
        int * b;
    private:
        A(){
          a = new int[100];
          b = new int(100);
        }
       ~A(){
          delete [] a;
          delete b;
        }
    }

当我说高效时,我的意思是关于类成员的所有数据都将在堆或堆栈中的内存中彼此存储在一起(实际上,我不确定它们将彼此存储在一起是否正确)。

不,您的说法不完全正确

a
b
是对象内部的变量。 它们都扩展了类的大小-至少扩展了
sizeof(int*)
的大小

根据构建对象的方式,此变量的内存在堆栈或堆上分配,如您所述:

新建A/int/etc
在堆上分配内存

A/int/etc.var
在堆栈上分配内存

您缺少的是在构造函数中分配的数据

  a = new int[100];

不是类对象的一部分。这是一些外部数据。在类对象中,只有一个 INT*<代码>成员(大小为4-8字节,这取决于体系结构),指向这个数据。

< P>首先,C++中没有堆或堆栈。相反,我们有自动存储持续时间和动态存储持续时间。具有自动存储持续时间的对象是作用域对象。当它超出范围时,会自动清理。另一方面,具有动态存储持续时间的对象不受其作用域的约束。它的生存期仅在程序显式结束时结束(通常这意味着调用
delete

现在在
A
中,有一个对象以自动存储持续时间
b
存储,另一个对象以动态存储持续时间
A
存储。这意味着
b
将存在于
A
实例所在的任何位置
a
也存在于
a
实例中,但它指向的内存将驻留在内存中的某个位置,但我们不知道在哪里。当实例被销毁时,
b
将自动清理,但
a
将需要在析构函数中进行特殊处理,否则内存将泄漏。你可以把它想象成

    A
+------+   +----------+
|   a->+---| 100 ints |
|   b  |   +----------+
+------+
就效率而言,你不应该真的担心。你应该使用你认为适合这份工作的类型。一旦你启动并运行了它,你就可以分析它,找出瓶颈所在。如果由于使用指针而看到太多缓存未命中,那么可以尝试将数据本地化到类本身


我还想提一下,如果你发现你自己写了代码>某个类型*Name=NeX/NeX[]/CUD>,那么你应该考虑使用<代码> STD:UnQuyPPTR/STD:UngQuyPPTR < /C>或<代码> STD::向量 .< /P>

首先是对成员原始指针的下侧(对于< <代码> MyClass < /代码>)是否强制

#包含声明
MyClass
的标题。这可能导致编译速度缓慢。为了解决这个问题,您可以使用带有正向声明的智能指针

第二个问题是,将类的所有成员存储在堆内存或堆栈内存中会更有效吗

class A{
    private:
        int * a;
        int * b;
    private:
        A(){
          a = new int[100];
          b = new int(100);
        }
       ~A(){
          delete [] a;
          delete b;
        }
    }

通常,最好仅在必要时使用指针。您通常应该在类中将成员声明为值。它将是本地的,出错的机会更少,分配更少,最终可能出错的事情更少,编译器可以始终知道它在指定的偏移量处,所以。。。它有助于在几个层次上优化和减少二进制数。

首先,不要考虑“效率”或优化。除非你有工作计划。相反,要集中精力使代码简单、易于阅读和维护。如果您使用的是standard,那么您的程序很可能会非常高效。然后,并且只有在需要的时候,才开始测量和分析潜在的瓶颈,并对其进行优化。我只想在给出的答案中添加一点,即通过动态分配内存,您必须记住,您的类现在基本上分为两个内存区域。在尝试复制(例如memcopy)或移动类时,请记住这一点。它必须至少是
sizeof(a)+sizeof(b)
,但可以更大。编译器可以在成员变量之间或在末尾插入填充。在本例中,我看不出原因——两个变量的大小相同,所以allignment也应该相同。为什么编译器可以分配更多的空间呢?正如您所看到的,编译器确实添加了填充以使其16字节对齐。最有可能的填充物是在最后。我只是觉得最好不要在没有要求的情况下声称某件东西是特定尺寸的。例如,谢谢。我固定了我的岗位。