堆栈/堆上的对象创建?

时间:2012-04-14 20:31:47

标签: c++ initialization stack heap

以下代码在堆栈上创建一个对象:

Object o;

在堆上创建对象时,我们可以使用:

Object* o;

o = new Object();

而不是:

Object* o = new Object();

当我们将堆对象创建分成两行并在第二行(o = new object())上调用构造函数时,这是否意味着在第一行(Object* o)上创建了指针堆?所以Object o将对象放在堆栈上,而Object* o将指针放在堆栈的未来对象上?

我的第二个问题涉及两行代码是否在类之外调用。我最近读过(Global memory management in C in stack or heap?)全局变量不包含在堆栈/堆中但实际上是内存的另一部分?如果是这种情况,Object* o会创建一个指针,它将位于内存的另一部分并指向堆对象吗?

7 个答案:

答案 0 :(得分:85)

实际上,两个声明都没有说明堆或堆栈:

Object o;

使用自动存储创建一个对象,这意味着存储位置由声明对象的上下文决定:如果代码在函数中,则恰好是调用堆栈。但是,该行也可以是类成员,或者如您所知,在函数/类之外。

说明为何不同:

struct Foo {
    Object o;
};

Foo* pf = new Foo();

现在,对象pf->o在堆上创建,而不是在堆栈上,即使(或者更确切地说,因为)它具有自动存储。< / p>

相反,

Object* p;

只是声明一个指针,仅此而已。 指针的存储与任何其他对象无法区分:它具有自动存储功能。此外,初始化表达式对变量存储没有影响。

指针指向的是一个完全不同的问题。它可能是堆分配的对象(例如,使用new),也可能指向另一个自动分配的对象。考虑:

Object o;
Object* p = &o;

答案 1 :(得分:10)

C ++提供了三种不同的方法来创建对象:

  1. 基于堆栈的临时对象
  2. 使用 new
  3. 基于堆
  4. 静态内存分配,例如全局变量和命名空间范围对象
  5. 考虑你的情况,

    Object* o;
    o = new Object();
    

    Object* o = new Object();
    

    两种形式都是一样的。这意味着在堆栈上创建指针变量o(假设您的变量不属于上面的3类),它指向堆中的内存,其中包含对象。

答案 2 :(得分:4)

两种形式相同,但有一个例外:临时,当创建和赋值分开时,新(Object *)具有未定义的值。编译器可以将它们组合在一起,因为未定义的指针不是特别有用。这与全局变量无关(除非声明是全局的,在这种情况下,对于两种形式它都是正确的。)

答案 3 :(得分:2)

A)

Object* o;
o = new Object();

`` B)

Object* o = new Object();

我认为A和B没有区别。在这两种情况下,o都是指向类Object的指针。 statement new Object()从堆内存创建一个Object类对象。赋值语句将分配的内存地址分配给指针o。

有一点我想提一下,来自堆的已分配内存大小总是sizeof(Object)而不是sizeof(Object)+ sizeof(void *)。

答案 4 :(得分:1)

在两个示例中,Object*类型的局部变量都在堆栈上分配。如果您的程序无法检测到差异,编译器可以从两个片段中自由生成相同的代码。

全局变量的内存区域与静态变量的内存区域相同 - 它既不在堆栈上也不在堆上。您可以通过在函数内声明static来在该区域中放置变量。这样做的结果是实例在函数的并发调用中变为 shared ,因此在使用静态时需要仔细考虑同步。

这是a link讨论正在运行的C程序的内存布局。

答案 5 :(得分:1)

C ++具有自动变量-没有堆栈变量。

自动变量表示C ++编译器自行处理内存分配/释放。 C ++可以自动处理任何类的对象-无论它是否具有动态分配的成员。通过C ++的有力保证,当执行超出声明自动变量的范围时,将自动调用对象的析构函数。在C ++对象内部,可以使用构造函数中的new进行许多动态分配,并且当将此类对象声明为自动变量时,将执行所有动态分配,然后在析构函数中将其释放。

C中的堆栈变量无法动态分配。 C语言中的堆栈可以存储指针,固定数组或结构-全部固定大小,并且这些内容以线性顺序分配在内存中。当C程序释放堆栈变量时,它只会将堆栈指针移回原处。

即使C ++程序可以使用堆栈内存段来存储原始类型,函数的args或其他内容,但这些都是由C ++编译器而不是程序开发人员决定的。因此,从概念上讲,等于C ++自动变量和C堆栈变量是错误的。

答案 6 :(得分:0)

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

  2. Object * o = new Object();

这两个语句都会在堆内存中创建对象,因为您正在使用“ new”创建对象。

要使对象创建能够在堆栈中进行,您需要遵循以下步骤:

Object o;
Object *p = &o;