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



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

假设我们声明一个类,如下所示:

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

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

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

是的,类中的所有成员变量在内存中都是连续的。因此,如果您的类对象在堆中(使用new创建(,则该对象将使用大小为(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 

如果考虑到文档:

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

但通常情况下,有一个布局,对象不会拆分到不同的内存区域(函数除外(,所以它会一起进入堆或堆栈(在您的情况下是堆(

对象表示

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

最新更新