如果我在堆上声明一个 class 实例,它的所有成员也会在堆上吗?

If I declare a class instance on the heap are all its members going to be on the heap as well?

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

是的,class 中的所有成员变量在内存中都是连续的。因此,如果您的 class 对象在堆中(使用 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 

假设我们像这样声明一个class:

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

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

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

如果考虑到 docs:

Like C, C++ doesn’t define layouts, just semantic constraints that must be met. Therefore different implementations do things differently.

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

Object representation

For an object of type T, object representation is the sequence of sizeof(T) objects of type unsigned char (or, equivalently, std::byte) beginning at the same address as the T object.