使用new创建对象时会发生什么

What happens when objects are created with new?

本文关键字:什么 new 创建对象 使用      更新时间:2023-10-16

这可能是一个微不足道的问题——每个人都知道用"new"操作符创建的对象是在堆上分配的,但是如果对象真的很复杂,有一些成员,局部变量等呢?所有这些存储在哪里?

假设我有一个引擎类的对象,非常复杂的一个。在我的代码中,我这样做了:

Engine* e = new Engine;

所以这很简单,指针指向堆栈,引擎的新实例在堆上创建。但在一个类引擎,我有一个字段,不是一个指针-在这种情况下,这个字段存储在哪里?如果在Engine类中,我有一个方法使用了局部变量,那么这些变量是否也存储在堆上呢?

结构/类的成员存储在为该结构/类的对象实例分配的内存块中(是在堆栈上还是在堆上无关紧要,但取决于对象的分配方式)。对象在内存中的大小是其数据成员的总大小,加上编译器为对齐目的在它们之间添加的填充。

new type分配一个动态内存块,大小至少为 sizeof(type)字节(对于内存管理器开销可能更大),然后调用该内存块上的类型构造函数。

例如,如果你有这样一个类:

class Engine
{
private:
    int numOfThings;
    ...
};

然后该类的任何实例占用sizeof(Engine)字节的内存,其中前4字节由numOfThings成员占用。这可能是自动记忆:

Engine engine;

也可以是动态内存:

Engine *engine = new Engine;

现在,假设Engine有其他自动或动态的成员,例如:

class Engine
{
private:
    int numOfThings;
    uint32_t values[16];
    std::string name;
    uint8_t *data;
    Engine()
    {
        data = new uint8_t[256];
    }
    ~Engine()
    {
        delete[] data;
    }
};

value成员的大小为(sizeof(uint32_t) * 16)(4*16=64)字节,加到Engine类的总大小上。

name成员的大小为sizeof(std::string)字节(取决于STL实现),它被添加到Engine类的总大小中。然而,std::string内部有一个指针指向它为字符数据分配的动态内存。该内存的大小不包括在Engine类的总大小中。

data指针的大小为sizeof(uint8_t*)字节(在32位系统上为4字节,在64位系统上为8字节),将其添加到Engine类的总大小中。data所指向的内存块大小为(sizeof(uint8_t) * 256)(1*256=256)字节,并且存储在动态内存的其他位置。

在类方法内部局部声明的变量不是类本身的一部分,因此不计入类的大小。只有在类定义中声明的数据成员才会被计算在类的大小中。