使用new创建对象时会发生什么
What happens when objects are created with new?
这可能是一个微不足道的问题——每个人都知道用"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)字节,并且存储在动态内存的其他位置。
在类方法内部局部声明的变量不是类本身的一部分,因此不计入类的大小。只有在类定义中声明的数据成员才会被计算在类的大小中。
- 如果我在 c++ 中以 new 的放置形式使用没有足够的内存,会发生什么情况?
- int** a = new int*[n]();这个函数有什么作用?
- "new int * **[10]"做什么?
- 有些时候,阶级必须"default copy c'tor" ?当我做"new Type[..]"时会发生什么?
- 对于没有功能的结构,"new (ptr) mystruct;"做什么?
- 使用泛型成员变量"placement new"结构/类数组的正确方法是什么?
- new和::new有什么区别
- 带"new"的指针和带"&variable"的指针有什么区别
- "a = new arr ***[num];"的含义是什么?
- 将内存分配给 2D 数组时,“new int*[rowCount];”的含义是什么?是 2D 数组,是指向数组的指针数组
- C++用法:" *(new int); "做什么?
- new _Elem[_Size]() 与 new _Elem[_Size]{} 有什么区别?
- int '*p = new int (5);' 和 'int *p = new int[5];' 有什么区别?
- (类 *对象;)和(object = new class();)之间有什么区别
- 除了使用 new 之外,什么会导致内存泄漏?(C++)
- "{}" "new int[5]{};"的目的是什么?
- 新的int()和new int []有什么区别
- "new Classname*[]"是什么意思?
- "new int(100)"做什么?
- 在混合 C/C++ 程序中协调 malloc 和 new 的"正确"方法是什么?