这种类型的内存是在堆还是堆栈上分配的?

时间:2009-01-09 01:27:52

标签: c++ memory-management stack heap

在C ++的上下文中(并非重要):

class Foo{
    private:
        int x[100];
    public:
        Foo();
}

我学到的东西告诉我,如果你像这样创建一个Foo实例:

Foo bar = new Foo();

然后在堆上分配数组x,但是如果你创建了一个Foo实例:

Foo bar;

然后它在堆栈上创建。

我无法在线查找资源以确认这一点。

5 个答案:

答案 0 :(得分:10)

稍微修改了你的例子:

class Foo{
    private:
        int x[100];
        int *y;
    public:
        Foo()
        {
           y = new int[100];
        }
        ~Foo()
        { 
           delete[] y; 
        }

}

示例1:

Foo *bar = new Foo();
  • x和y在堆上:
  • sizeof(Foo *)在堆栈上创建。
  • sizeof(int)* 100 * 2 + sizeof(int *)在堆上

示例2:

Foo bar;
  • x在堆栈上,y在堆上
  • sizeof(int)* 100位于堆栈(x)+ sizeof(int *)
  • sizeof(int)* 100在堆上(y)

由于类/结构对齐,实际大小可能略有不同,具体取决于您的编译器和平台。

答案 1 :(得分:10)

严格地说,根据标准,对象不需要存在于堆栈或堆上。该标准定义了3种类型的“存储持续时间”,但没有说明存储必须如何实现:

  1. 静态存储时间
  2. 自动存储时间
  3. 动态存储时间
  4. 使用堆栈通常(几乎总是)实现自动存储持续时间。

    动态存储持续时间通常使用堆(最终通过malloc())实现,但即使编译器的用户也可以覆盖它。

    静态存储持续时间通常称为全局(或静态存储)。

    标准对此有所说明(以下是各种各样的3.7 - 存储持续时间的摘录):

      

    静态和自动存储持续时间   与引入的对象相关联   通过声明(3.1)和隐含的   由实现创建(12.2)。   动态存储持续时间是   与使用的对象相关联   operator new(5.3.4)。

         

    ...

         

    所有既没有动态的物体   储存时间也不是当地的   静态存储时间。存储   因为这些物体应该持久   计划的持续时间(3.6.2,   3.6.3)。

         

    ...

         

    显式声明自动的本地对象   或注册或未明确声明   static或extern有自动   储存期限。存储   这些物体持续到阻挡   他们被创建退出。

         

    ...

         

    可以动态创建对象   在程序执行期间(1.9),使用   new-expressions(5.3.4),并销毁   使用delete-expressions(5.3.5)。一个C.   + +实现提供对动态存储的访问和管理   全球分配职能   operator new和operator new []和   全局释放函数   operator delete和operator delete []。

         

    ...

         

    库提供默认值   全球分配的定义   和释放功能。一些   全球分配和解除分配   功能是可替换的(18.4.1)

    最后(关于示例类中的数组):

      

    3.7.4子对象的持续时间[basic.stc.inherit]

         

    成员子对象,基类子对象和数组元素的存储持续时间是其完整的存储持续时间   对象(1.8)。

答案 2 :(得分:7)

Foo类型的对象按顺序存储100个整数的大小。 如果你在堆栈上创建它,你将在堆栈中获得它。 如果你用new做,它将作为对象的一部分在堆上。

这是语言规范的一部分,我不确定你的问题是什么。

答案 3 :(得分:2)

是的,如果在堆上创建x对象,将在堆上创建成员数组Foo。当您为Foo分配动态内存时,您要求的内存长度为sizeof(Foo)(可能还有一些内存开销,但暂时忽略它),在示例代码中意味着大小为100 int秒。这个具有,可以使Foo类型的对象(及其内部数据)的生命周期跨越范围。

如果你没有在堆上创建Foo对象,并且Foo的内部数组不是指向{{1}中new分配内存的指针然后,将在堆栈上创建内部数组。同样,必须是这样的,以便在范围结束时自动清理数组而不需要任何Foo。具体地,

delete
无论是在堆栈上还是在堆上创建struct Foo { int* y; Foo() : y(new int()) { } ~Foo() { delete y; } }; 对象,

都会在堆上创建y

答案 4 :(得分:1)

你的意思是

Foo* bar = new Foo(); 

我想。 那个是在堆中创建的。