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

时间:2016-11-03 21:02:45

标签: c++

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

假设我有类Engine的对象,非常复杂。在我的代码的某处,我这样做:

Engine* e = new Engine;

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

1 个答案:

答案 0 :(得分:1)

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

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)个字节,并存储在动态内存的其他位置。

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