C++对象创建时的内存分配
Memory allocation on C++ object creation
在下面的C类上创建对象期间,可以观察到不同大小的内存分配
class C {
int i;
int j;
};
void f() {
C *c = new C;
C *c2 = new C[2];
C (*c3)[2] = new C[2][2];
}
c被分配有8个字节;
c2被分配有8*2+4个字节;
c3被分配有8*2*2+4个字节。
为什么c2和c3需要4个字节?
请记住,C++将内存分配和对象表达式分离。默认数组新表达式T * p = new T[N];
为N
对象分配足够的内存,构造这些对象。在另一端,delete[] p;
必须调用所有这些元素的析构函数,然后释放内存。
虽然分配和释放内存是由平台处理的,并且可释放内存可以通过单个指针值很好地识别给操作系统,但构建和销毁对象更为复杂。实际对象的数量必须存储在某个地方,为此,标准允许C++实现请求比N * sizeof(T)
更多的内存。的确,指针p
将始终指向N
对象数组的开头,但p
不必是底层内存分配器返回的同一指针。(事实上,p
保证精确地是底层分配结果的值,偏移了多余的内存量。)
细节完全由实施决定。不过,一些平台提供了额外的保障;例如,安腾ABI(它将额外的数据称为"数组cookie")表示new T[N]
的内存布局如下:
+- alignof(T) --+-- sizeof(T) --+-- sizeof(T) --+-- sizeof(T) --+-- ...
| ***** [8B: N] | 1st element | 2nd element | 3rd element | .....
+---------------+---------------+---------------+---------------+-- ...
A A
| |_ result of "new T[N]"
|
|_ value returned "operator new[]()"
来自标准([expr.mew]
节):
新表达式将请求的空间量作为类型
std::size_t
的第一个参数传递给分配函数。该论点应不小于正在创建的对象的大小;只有当对象是数组时,它才可能大于正在创建的对象的大小。
显然,该标准期望一些附加信息与动态分配的数组一起存储。
现在,使用调试器来查看这些额外字节中填充了什么,并确定编译器何时可能需要这些额外信息来完成其工作。
(提示:修复程序,使其不会泄漏内存)
许多编译器使用new[]返回的指针前的4个字节来存储实际分配的对象数。这完全取决于实现,重要的是要记住,指针算术会使您超出分配的内存范围,从而导致未定义的行为
- Win32编译器选项和内存分配
- 多个文件的内存分配错误"在抛出 'std :: bad_alloc' what (): std :: bad_alloc 的实例后终止调用" [C++]
- 当需要超过16GB的连续内存时,内存分配失败
- 尝试摆脱任何堆内存分配
- 以下代码执行哪种内存分配(动态或静态)?
- 开放 CV 中的动态内存分配,用于视频处理
- 为什么类和 main() 函数中也有动态内存分配
- 使用 NTAllocateVirtualMemory 和 GetProcAddress 的内存分配问题不起作用
- C++:矢量分配器行为、内存分配和智能指针
- 介于 [固定数组] 和 [带内存分配的指针] 之间的性能
- Linux C++ 中的页面对齐内存分配
- 整数内存分配/释放
- 将内存分配返回值强制转换为 TYPE 数组
- C++程序什么都不做,但瓦尔格林德显示内存分配
- 给定特定内存地址的数组的动态内存分配
- 如何完成内存分配
- 我刚刚了解了C++中的动态内存分配
- 在先前调用 string::find 后添加内存分配和内存集会导致它返回 npos.为什么?
- 对于堆上的页面对齐内存分配是否有任何优化或不同的 API?
- 无法删除布尔动态内存分配