【问题标题】:If I declare a class instance on the heap are all its members going to be on the heap as well?如果我在堆上声明一个类实例,它的所有成员也会在堆上吗?
【发布时间】:2020-11-18 05:27:25
【问题描述】:

我想知道如果我在堆上声明一个类实例(new),它的成员是否也会在堆上,即使它们不是使用 new 关键字创建的?

【问题讨论】:

  • 是吗?他们怎么可能最终在堆栈上?你有一个你认为最终可能会堆积起来的例子吗? (另外,我不是反对者。) PS - 构造函数和函数将使用堆栈作为局部变量,但它们不是成员变量。
  • 一个类实例中的所有数据在内存中都是连续的。这只是一个对象。
  • 但是,如果一个类包含指针,这些指针可以指向堆栈或静态数据。
  • 他们不确定的唯一方法是,如果该类被声明为没有成员。不存在的成员不会在堆上

标签: c++ object memory heap-memory stack-memory


【解决方案1】:

假设我们这样声明一个类:

class Foo
{
private:
    std::string Bar;
public:
    Foo(std::string Bar);
}

当您创建该类的新对象时,它的数据成员将保存在 与对象本身相同的位置,这意味着如果您执行类似 Foo* f = new Foo("hello"); 的操作,所有数据都将保存在存储在堆中,但如果你这样做Foo f = Foo("hello");,它将存储在堆栈中。

为什么会这样?当你创建像foo这样的类对象时,它的数据成员被称为sub-objects,从内存的角度来看,类对象和它的子对象是一个,这意味着如果你创建一个foo的对象在堆上,它的所有子对象都将存储在堆上,并且它们与类对象本身是一回事。当您创建一个类的实例时,当您尝试访问它的数据成员时,您不会被重定向到其他地方,您只是访问对象本身的特定部分。

【讨论】:

    【解决方案2】:

    如果您考虑到docs

    与 C 一样,C++ 不定义布局,只定义必须满足的语义约束。因此,不同的实现会做不同的事情。

    但通常情况下,有一个布局并且对象不会在不同的内存区域(函数除外)中拆分,因此它会一起进入堆或堆栈(在您的情况下为堆。)

    对象表示

    对于T 类型的对象,对象表示是unsigned char 类型的sizeof(T) 对象的序列(或等价的std::byte),从与T 对象相同的地址开始。

    【讨论】:

      【解决方案3】:

      是的,您的类中的所有成员变量在内存中都是连续的。因此,如果您的类对象在堆中(使用 new 创建),则该对象将使用最多 sizeof(YourClass) 的内存。大小取决于其所有非静态成员的单独大小(也可能应用一些填充)。

      class ExampleClass {
      public:
          int first;
          float second;
      };
      
      void test() {
          ExampleClass *obj = new ExampleClass;
      
          std::cout << obj << " object address \n";
          std::cout << &obj->first << " first member address \n";
          std::cout << &obj->second << " second member address \n";
      
          delete obj;
      }
      
      Will print:
      0x55c0f4c85eb0 object address
      0x55c0f4c85eb0 first member address
      0x55c0f4c85eb4 second member address 
      

      【讨论】:

      • [...]object is in heap (created with new)[...] 你需要小心这样的陈述。首先,还有placement new 允许在堆栈上使用new 创建一个对象。你可以为一个类重载newdeleteoperator。 new 说了一些关于 storage duration 的事情。虽然具有动态存储持续时间的对象通常存在于堆中,但这不是必需的。
      猜你喜欢
      • 1970-01-01
      • 2010-11-19
      • 1970-01-01
      • 2017-01-30
      • 2018-09-09
      • 2012-02-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多