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

时间:2022-06-28 04:00:21

In the context of C++ (not that it matters):

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

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

What I've learnt tells me that if you create an instance of Foo like so:

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

Foo bar = new Foo();

Then the array x is allocated on the heap, but if you created an instance of Foo like so:

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

Foo bar;

Then it's created on the stack.

然后它在堆栈上创建。

I can't find resources online to confirm this.

我在网上找不到资源来证实这一点。

5 个解决方案

#1


10  

Given a slight modification of your example:

鉴于您的示例略有修改:

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

}

Example 1:

Foo *bar = new Foo();
  • x and y are on the heap:
  • x和y在堆上:

  • sizeof(Foo*) is created on the stack.
  • sizeof(Foo *)在堆栈上创建。

  • sizeof(int) * 100 * 2 + sizeof(int *) is on the heap
  • sizeof(int)* 100 * 2 + sizeof(int *)在堆上


Example 2:

Foo bar;
  • x is on the stack, and y is on the heap
  • x在堆栈上,y在堆上

  • sizeof(int) * 100 is on the stack (x) + sizeof(int*)
  • sizeof(int)* 100位于堆栈(x)+ sizeof(int *)

  • sizeof(int) * 100 is on the heap (y)
  • sizeof(int)* 100在堆上(y)

Actual sizes may differ slightly due to class/struct alignment depending on your compiler and platform.

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

#2


10  

Strictly speaking, according to the standard the object need not exist on a stack or heap. The standard defines 3 types of 'storage duration', but doesn't state exactly how the storage must be implemented:

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

  1. static storage duration
  2. 静态存储持续时间

  3. automatic storage duration
  4. 自动存储时间

  5. dynamic storage duration
  6. 动态存储持续时间

Automatic storage duration is typically (nearly always) implemented using the stack.

使用堆栈通常(几乎总是)实现自动存储持续时间。

Dynamic storage duration is typically implemented using the heap (ultimately via malloc()), though this can be overridden even by the compiler's user.

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

Static storage duration is what it typically known as globals (or static storage).

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

The standard has this to say about these things (the following are excerpts form various bits of 3.7 - Storage Duration):

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

Static and automatic storage durations are associated with objects introduced by declarations (3.1) and implicitly created by the implementation (12.2). The dynamic storage duration is associated with objects created with operator new (5.3.4).

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

...

All objects which neither have dynamic storage duration nor are local have static storage duration. The storage for these objects shall last for the duration of the program (3.6.2, 3.6.3).

既没有动态存储持续时间也没有本地的所有对象都有静态存储持续时间。这些对象的存储应持续到程序的持续时间(3.6.2,3.6.3)。

...

Local objects explicitly declared auto or register or not explicitly declared static or extern have automatic storage duration. The storage for these objects lasts until the block in which they are created exits.

显式声明为auto或者注册或未显式声明为static或extern的本地对象具有自动存储持续时间。这些对象的存储将持续到创建它们的块为止。

...

Objects can be created dynamically during program execution (1.9), using new-expressions (5.3.4), and destroyed using delete-expressions (5.3.5). A C + + implementation provides access to, and management of, dynamic storage via the global allocation functions operator new and operator new[] and the global deallocation functions operator delete and operator delete[].

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

...

The library provides default definitions for the global allocation and deallocation functions. Some global allocation and deallocation functions are replaceable (18.4.1)

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

And finally (regarding the array in your example class):

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

3.7.4 Duration of sub-objects [basic.stc.inherit]

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

The storage duration of member subobjects, base class subobjects and array elements is that of their complete object (1.8).

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

#3


7  

An object of type Foo takes the size of 100 ints stored in sequence. If you create it on the stack, you will be getting it all on the stack. If you do it with new, it'll be on the heap as part of the object.

Foo类型的对象按顺序存储100个int的大小。如果您在堆栈上创建它,您将在堆栈中获取所有内容。如果你用new做它,它将作为对象的一部分在堆上。

This is part of the language specification, I'm not sure what your question is.

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

#4


2  

Yes, the member array x will be created on the heap if you create the Foo object on the heap. When you allocate dynamic memory for Foo you are asking for memory of length sizeof(Foo) (plus possibly some memory overhead, but let's ignore that for the time being), which in your sample code implies the size of 100 ints. This has to be case for the lifespan of objects of type Foo (and their internal data) to cross scopes.

是的,如果在堆上创建Foo对象,则将在堆上创建成员数组x。当你为Foo分配动态内存时,你要求长度sizeof(Foo)的内存(加上可能的一些内存开销,但暂时忽略它),在你的示例代码中暗示了100个int的大小。这必须是Foo类型的对象(及其内部数据)的生命周期跨越范围的情况。

If you don't create the Foo object on the heap, and the internal array of Foo isn't a pointer to which you allocate memory with new in Foo's constructor then that internal array will be created on the stack. Again, this has to be the case in order for the array to automatically be cleaned without any deletes when the scope ends. Specifically,

如果你没有在堆上创建Foo对象,并且Foo的内部数组不是在Foo的构造函数中用new分配内存的指针,那么将在堆栈上创建该内部数组。同样,必须是这样的,以便在范围结束时自动清理阵列而不进行任何删除。特别,

struct Foo {
    int* y;
    Foo() : y(new int()) { }
    ~Foo() { delete y; }
};

will create y on the heap regardless of whether a Foo object was created on the stack or on the heap.

无论是在堆栈上还是在堆上创建Foo对象,都将在堆上创建y。

#5


1  

You mean

Foo* bar = new Foo(); 

I suppose. That is created in the heap.

我想。这是在堆中创建的。

#1


10  

Given a slight modification of your example:

鉴于您的示例略有修改:

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

}

Example 1:

Foo *bar = new Foo();
  • x and y are on the heap:
  • x和y在堆上:

  • sizeof(Foo*) is created on the stack.
  • sizeof(Foo *)在堆栈上创建。

  • sizeof(int) * 100 * 2 + sizeof(int *) is on the heap
  • sizeof(int)* 100 * 2 + sizeof(int *)在堆上


Example 2:

Foo bar;
  • x is on the stack, and y is on the heap
  • x在堆栈上,y在堆上

  • sizeof(int) * 100 is on the stack (x) + sizeof(int*)
  • sizeof(int)* 100位于堆栈(x)+ sizeof(int *)

  • sizeof(int) * 100 is on the heap (y)
  • sizeof(int)* 100在堆上(y)

Actual sizes may differ slightly due to class/struct alignment depending on your compiler and platform.

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

#2


10  

Strictly speaking, according to the standard the object need not exist on a stack or heap. The standard defines 3 types of 'storage duration', but doesn't state exactly how the storage must be implemented:

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

  1. static storage duration
  2. 静态存储持续时间

  3. automatic storage duration
  4. 自动存储时间

  5. dynamic storage duration
  6. 动态存储持续时间

Automatic storage duration is typically (nearly always) implemented using the stack.

使用堆栈通常(几乎总是)实现自动存储持续时间。

Dynamic storage duration is typically implemented using the heap (ultimately via malloc()), though this can be overridden even by the compiler's user.

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

Static storage duration is what it typically known as globals (or static storage).

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

The standard has this to say about these things (the following are excerpts form various bits of 3.7 - Storage Duration):

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

Static and automatic storage durations are associated with objects introduced by declarations (3.1) and implicitly created by the implementation (12.2). The dynamic storage duration is associated with objects created with operator new (5.3.4).

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

...

All objects which neither have dynamic storage duration nor are local have static storage duration. The storage for these objects shall last for the duration of the program (3.6.2, 3.6.3).

既没有动态存储持续时间也没有本地的所有对象都有静态存储持续时间。这些对象的存储应持续到程序的持续时间(3.6.2,3.6.3)。

...

Local objects explicitly declared auto or register or not explicitly declared static or extern have automatic storage duration. The storage for these objects lasts until the block in which they are created exits.

显式声明为auto或者注册或未显式声明为static或extern的本地对象具有自动存储持续时间。这些对象的存储将持续到创建它们的块为止。

...

Objects can be created dynamically during program execution (1.9), using new-expressions (5.3.4), and destroyed using delete-expressions (5.3.5). A C + + implementation provides access to, and management of, dynamic storage via the global allocation functions operator new and operator new[] and the global deallocation functions operator delete and operator delete[].

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

...

The library provides default definitions for the global allocation and deallocation functions. Some global allocation and deallocation functions are replaceable (18.4.1)

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

And finally (regarding the array in your example class):

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

3.7.4 Duration of sub-objects [basic.stc.inherit]

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

The storage duration of member subobjects, base class subobjects and array elements is that of their complete object (1.8).

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

#3


7  

An object of type Foo takes the size of 100 ints stored in sequence. If you create it on the stack, you will be getting it all on the stack. If you do it with new, it'll be on the heap as part of the object.

Foo类型的对象按顺序存储100个int的大小。如果您在堆栈上创建它,您将在堆栈中获取所有内容。如果你用new做它,它将作为对象的一部分在堆上。

This is part of the language specification, I'm not sure what your question is.

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

#4


2  

Yes, the member array x will be created on the heap if you create the Foo object on the heap. When you allocate dynamic memory for Foo you are asking for memory of length sizeof(Foo) (plus possibly some memory overhead, but let's ignore that for the time being), which in your sample code implies the size of 100 ints. This has to be case for the lifespan of objects of type Foo (and their internal data) to cross scopes.

是的,如果在堆上创建Foo对象,则将在堆上创建成员数组x。当你为Foo分配动态内存时,你要求长度sizeof(Foo)的内存(加上可能的一些内存开销,但暂时忽略它),在你的示例代码中暗示了100个int的大小。这必须是Foo类型的对象(及其内部数据)的生命周期跨越范围的情况。

If you don't create the Foo object on the heap, and the internal array of Foo isn't a pointer to which you allocate memory with new in Foo's constructor then that internal array will be created on the stack. Again, this has to be the case in order for the array to automatically be cleaned without any deletes when the scope ends. Specifically,

如果你没有在堆上创建Foo对象,并且Foo的内部数组不是在Foo的构造函数中用new分配内存的指针,那么将在堆栈上创建该内部数组。同样,必须是这样的,以便在范围结束时自动清理阵列而不进行任何删除。特别,

struct Foo {
    int* y;
    Foo() : y(new int()) { }
    ~Foo() { delete y; }
};

will create y on the heap regardless of whether a Foo object was created on the stack or on the heap.

无论是在堆栈上还是在堆上创建Foo对象,都将在堆上创建y。

#5


1  

You mean

Foo* bar = new Foo(); 

I suppose. That is created in the heap.

我想。这是在堆中创建的。