简体   繁体   English

在堆栈/堆上创建对象?

[英]Object creation on the stack/heap?

The following code creates an object on the stack:以下代码在堆栈上创建一个对象:

Object o;

When creating an object on the heap we can use:在堆上创建对象时,我们可以使用:

Object* o;

o = new Object();

rather than:而不是:

Object* o = new Object();

When we split the heap object-creation over two lines and call the constructor on the second line ( o = new object() ), does this mean in the first line ( Object* o ) the pointer was created on the stack?当我们将堆对象创建分成两行并在第二行( o = new object() )上调用构造函数时,这是否意味着在第一行( Object* o )中,指针是在堆栈上创建的? So Object o puts the object on the stack, whereas Object* o puts the pointer to a future object on the stack?那么Object o将对象放在堆栈上,而Object* o将指向未来对象的指针放在堆栈上?

My second question involves if the two lines of code were called outside of a class.我的第二个问题涉及这两行代码是否是在类之外调用的。 I recently read ( Global memory management in C in stack or heap? ) that global variables are not contained on the stack/heap but actually another part of memory?我最近读到( 堆栈或堆中 C 中的全局内存管理? )全局变量不包含在堆栈/堆中,而实际上是内存的另一部分? If this is the case, would Object* o create a pointer which would sit in this other part of the memory and it points to the heap object?如果是这种情况, Object* o是否会创建一个指针,该指针将位于内存的另一部分并指向堆对象?

Actually, neither statement says anything about heap or stack.实际上,这两个语句都没有说明堆或堆栈。 The code代码

Object o;

creates one of the following, depending on its context:根据上下文创建以下之一:

  • a local variable with automatic storage,具有自动存储功能的局部变量,
  • a static variable at namespace or file scope,命名空间或文件范围内的静态变量,
  • a member variable that designates the subobject of another object.指定另一个对象的子对象的成员变量。

This means that the storage location is determined by the context in which the object is defined.这意味着存储位置由定义对象的上下文决定。 In addition, the C++ standard does not talk about stack vs heap storage.此外,C++ 标准没有讨论堆栈堆存储。 Instead, it talks about storage duration , which can be either automatic , dynamic , static or thread-local .相反,它谈论的是storage duration ,它可以是automaticdynamicstaticthread-local However, most implementations implement automatic storage via the call stack, and dynamic storage via the heap.然而,大多数实现通过调用栈实现自动存储,通过堆实现动态存储。

Local variables, which have automatic storage, are thus created on the stack.因此,在堆栈上创建了具有自动存储功能的局部变量。 Static (and thread-local) objects are generally allocated in their own memory regions, neither on the stack nor on the heap.静态(和线程本地)对象通常分配在它们自己的内存区域中,既不在堆栈上也不在堆上。 And member variables are allocated wherever the object they belong to is allocated.并且成员变量被分配到它们所属的对象被分配的地方。 They have their containing object's storage duration.它们有其包含对象的存储持续时间。

To illustrate this with an example:用一个例子来说明这一点:

struct Foo {
    Object o;
};

Foo foo;

int main() {
    Foo f;
    Foo* p = new Foo;
    Foo* pf = &f;
}

Now where is the object Foo::o (that is, the subobject o of an object of class Foo ) created?现在对象Foo::o (即Foo类对象的子对象o )在哪里创建? It depends:这取决于:

  • foo.o has static storage because foo has static storage, and therefore lives neither on the stack nor on the heap. foo.o有静态存储,因为foo有静态存储,因此既不在栈上也不在堆上。
  • fo has automatic storage since f has automatic storage (= it lives on the stack). fo有自动存储,因为f有自动存储(= 它存在于堆栈中)。
  • p->o has dynamic storage since *p has dynamic storage (= it lives on the heap). p->o具有动态存储,因为*p具有动态存储(= 它存在于堆中)。
  • pf->o is the same object as fo because pf points to f . pf->ofo是同一个对象,因为pf指向f

In fact, both p and pf in the above have automatic storage.其实上面的ppf都有自动存储。 A pointer's storage is indistinguishable from any other object's, it is determined by context.指针的存储与任何其他对象的存储没有区别,它由上下文决定。 Furthermore, the initialising expression has no effect on the pointer storage.此外,初始化表达式对指针存储没有影响。

The pointee (= what the pointer points to) is a completely different matter, and could refer to any kind of storage: *p is dynamic, whereas *pf is automatic.指针(= 指针指向的内容)是完全不同的事情,可以指任何类型的存储: *p是动态的,而*pf是自动的。

C++ offers three different ways to create objects: C++ 提供了三种不同的方式来创建对象:

  1. Stack-based such as temporary objects基于栈的比如临时对象
  2. Heap-based by using new使用的基于堆的
  3. Static memory allocation such as global variables and namespace-scope objects静态内存分配,例如全局变量和命名空间范围的对象

Consider your case,考虑你的情况,

Object* o;
o = new Object();

and:和:

Object* o = new Object();

Both forms are the same.两种形式都是一样的。 This means that a pointer variable o is created on the stack (assume your variables does not belong to the 3 category above) and it points to a memory in the heap, which contains the object.这意味着在堆栈上创建了一个指针变量 o(假设您的变量不属于上述 3 类),它指向堆中包含对象的内存。

The two forms are the same with one exception: temporarily, the new (Object *) has an undefined value when the creation and assignment are separate.这两种形式是一样的,只有一个例外:当创建和赋值分开时,新的(Object *)暂时有一个未定义的值。 The compiler may combine them back together, since the undefined pointer is not particularly useful.编译器可能会将它们重新组合在一起,因为未定义的指针不是特别有用。 This does not relate to global variables (unless the declaration is global, in which case it's still true for both forms).这与全局变量无关(除非声明是全局的,在这种情况下,这两种形式仍然适用)。

C++ has Automatic variables - not Stack variables. C++ 有自动变量——而不是堆栈变量。

Automatic variable means that C++ compiler handles memory allocation / free by itself.自动变量意味着 C++ 编译器自己处理内存分配/释放。 C++ can automatically handle objects of any class - no matter whether it has dynamically allocated members or not. C++ 可以自动处理任何类的对象——不管它是否有动态分配的成员。 It's achieved by strong guarantee of C++ that object's destructor will be called automatically when execution is going out of scope where automatic variable was declared.它是通过 C++ 的强大保证实现的,当执行超出声明自动变量的范围时,将自动调用对象的析构函数。 Inside of a C++ object can be a lot of dynamic allocations with new in constructor, and when such an object is declared as an automatic variable - all dynamic allocations will be performed, and freed then in destructor.在 C++ 对象内部可以有很多动态分配,在构造函数中有new ,并且当这样的对象被声明为自动变量时 - 所有动态分配将被执行,然后在析构函数中释放。

Stack variables in C can't be dynamically allocated. C 中的堆栈变量不能动态分配。 Stack in C can store pointers, or fixed arrays or structs - all of fixed size, and these things are being allocated in memory in linear order. C 中的堆栈可以存储指针、固定数组或结构——所有的大小都是固定的,这些东西在内存中以线性顺序分配。 When a C program frees a stack variable - it just moves stack pointer back and nothing more.当 C 程序释放堆栈变量时 - 它只是将堆栈指针移回,仅此而已。

Even though C++ programs can use Stack memory segment for storing primitive types, function's args, or other, - it's all decided by C++ compiler, not by program developer.尽管 C++ 程序可以使用 Stack 内存段来存储原始类型、函数的参数或其他,但这都是由 C++ 编译器决定的,而不是由程序开发人员决定的。 Thus, it is conceptually wrong to equal C++ automatic variables and C stack variables.因此,将 C++ 自动变量和 C 堆栈变量相等在概念上是错误的。

A)一种)

Object* o;
o = new Object();

`` B) ``乙)

Object* o = new Object();

I think A and B has no difference.我认为A和B没有区别。 In both the cases o is a pointer to class Object.在这两种情况下,o 都是指向 Object 类的指针。 statement new Object() creates an object of class Object from heap memory.语句 new Object() 从堆内存中创建一个 Object 类的对象。 Assignment statement assigns the address of allocated memory to pointer o.赋值语句将分配的内存地址赋值给指针o。

One thing I would like to mention that size of allocated memory from heap is always the sizeof(Object) not sizeof(Object) + sizeof(void *).我想提到的一件事是,从堆分配的内存大小始终是 sizeof(Object) 而不是 sizeof(Object) + sizeof(void *)。

In both your examples, local variables of Object* type are allocated on the stack.在您的两个示例中, Object*类型的局部变量都在堆栈上分配。 The compiler is free to produce the same code from both snippets if there is no way for your program to detect a difference.如果您的程序无法检测差异,则编译器可以自由地从两个片段生成相同的代码。

The memory area for global variables is the same as the memory area for static variables - it's neither on the stack nor on the heap.全局变量的内存区域与静态变量的内存区域相同 - 它既不在堆栈上也不在堆上。 You can place variables in that area by declaring them static inside the function.您可以通过在函数内将变量声明为static来将变量放置在该区域中。 The consequence of doing so is that the instance becomes shared among concurrent invocations of your function, so you need to carefully consider synchronization when you use statics.这样做的结果是实例在函数的并发调用之间共享,因此在使用静态时需要仔细考虑同步。

Here is a link to a discussion of the memory layout of a running C program.这是有关正在运行的 C 程序的内存布局的讨论的链接

  1. Object* o;对象* o; o = new Object(); o = 新对象();

  2. Object* o = new Object(); Object* o = new Object();

Both these statement creates the object in the heap memory since you are creating the object using "new".由于您使用“new”创建对象,因此这两个语句都在堆内存中创建对象。

To be able to make the object creation happen in the stack, you need to follow this:为了能够在堆栈中创建对象,您需要遵循以下步骤:

Object o;
Object *p = &o;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM