C++ 在堆栈/堆上创建对象?

C++ 在堆栈/堆上创建对象?,c++,initialization,stack,heap,C++,Initialization,Stack,Heap,以下代码在堆栈上创建一个对象: Object o; 在堆上创建对象时,我们可以使用: Object* o; o = new Object(); 而不是: Object* o = new Object(); 当我们将堆对象创建拆分为两行并在第二行(o=newobject())上调用构造函数时,这是否意味着在第一行(object*o)中在堆栈上创建了指针?所以objecto将对象放在堆栈上,而Object*o将指向未来对象的指针放在堆栈上 我的第二个问题涉及到这两行代码是否在类之外调用。我最

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

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

Object* o;

o = new Object();
而不是:

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


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

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

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

全局变量的内存区域与静态变量的内存区域相同——它既不在堆栈上,也不在堆上。通过在函数中声明变量
static
,可以将变量放置在该区域中。这样做的结果是,实例在函数的并发调用之间共享,因此在使用静力学时需要仔细考虑同步。
这里讨论的是运行中的C程序的内存布局。

实际上,这两个语句都没有提到堆或堆栈。代码

Object o;
根据上下文创建以下内容之一:

  • 具有自动存储功能的局部变量
  • 命名空间或文件范围中的静态变量
  • 指定另一个对象的子对象的成员变量
这意味着存储位置由定义对象的上下文确定。此外,C++标准不谈论堆栈和堆存储。相反,它讨论的是线程,可以是自动的、动态的、静态的或线程本地的。然而,大多数实现通过调用堆栈实现自动存储,通过堆实现动态存储

因此,在堆栈上创建具有自动存储的局部变量。静态(和线程本地)对象通常分配在它们自己的内存区域中,既不在堆栈上也不在堆上。成员变量分配到它们所属的对象的任何位置。它们具有其包含对象的存储持续时间

用一个例子来说明这一点:

struct Foo {
    Object o;
};

Foo foo;

int main() {
    Foo f;
    Foo* p = new Foo;
    Foo* pf = &f;
}
现在,对象
Foo::o
(即类
Foo
的对象的子对象
o
)在哪里创建?这取决于:

  • foo.o
    具有静态存储,因为
    foo
    具有静态存储,因此既不存在于堆栈上,也不存在于堆上
  • f.o
    具有自动存储,因为
    f
    具有自动存储(=它位于堆栈上)
  • p->o
    具有动态存储,因为
    *p
    具有动态存储(=它位于堆上)
  • pf->o
    是与
    f.o
    相同的对象,因为
    pf
    指向
    f
事实上,上面的
p
pf
都有自动存储。指针的存储与任何其他对象的存储是无法区分的,它是由上下文决定的。此外,初始化表达式对指针存储没有影响

指针对象(=指针指向的对象)是一个完全不同的问题,可以指任何类型的存储:
*p
是动态的,而
*pf
是自动的。

a)

`` (B)

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


我想提到的一点是,从堆中分配的内存大小始终是sizeof(Object)而不是sizeof(Object)+sizeof(void*)。

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

  • 基于堆栈的对象,例如临时对象
  • 通过使用新的
  • 静态内存分配,如全局变量和命名空间作用域对象
  • 考虑一下你的情况

    Object* o;
    o = new Object();
    
    以及:


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

    C++有自动变量,而不是堆栈变量

    自动变量意味着C++编译器自行处理内存分配/空闲。C++可以自动处理任何类的对象——无论它是否有动态分配的成员。通过C++的强大保证,当执行超出声明自动变量的范围时,对象析构函数将自动调用。C++对象的内部可以在构造函数中使用大量的动态分配,使用<代码>新< /C>,当这样的对象被声明为自动变量时,所有动态分配都将被执行,然后在析构函数中释放。 无法动态分配C中的堆栈变量。C中的堆栈可以存储指针、固定数组或结构——所有这些都是固定大小的,这些东西都在l中的内存中分配

    Object* o = new Object();
    
    Object* o;
    o = new Object();
    
    Object* o = new Object();
    
    Object o;
    Object *p = &o;