块分配与单个对象分配的主要区别是什么。让我们说
int iCount = 5;
int i = 0;
while(i < iCount)
{
f = new foo();
i++;
}
//////////////////
foo* f = new foo[iCount];
第二种方法会为我节省一些内存空间吗?我听说我们分配的每个对象都被 16 个管理字节包围。因此块分配将仅使用一个标头保护。是真的吗?
您所做的每个分配还分配分配标头(有时还分配一些页脚保护结构),这取决于分配器使用的算法。在这里,您可以找到其中一种算法的描述。
当您分配数组时,分配器(主要malloc()
是sizeof(element) * count
底部)。
无论如何(因为问题是用c++标记的),优秀的 C++ 程序员应该避免手动管理内存。对于数组,使用标准库类(vector
、、map
等list
)。尽可能使用 RAII,不要使用原始指针,而是使用“智能”指针。
注意:我在这里写的所有内容都完全取决于所使用的算法,因此关于数组分配的段落可能不适用于所有可能的内存分配算法。因此,直接回答“块分配与单个对象分配之间的主要区别是什么”也取决于算法。
另一个非常重要的区别是异常安全。在您的代码中:
int iCount = 5;
int i = 0;
while(i < iCount)
{
f = new foo();
i++;
}
您必须非常非常小心,以免产生内存泄漏;您绝对必须记住所有内容foo
才能在出现异常时正确清理它。如果这段代码在构造函数中,那么在析构函数中释放是不够的,因为如果抛出异常,你的对象永远不会复活,析构函数也不会被调用。这进一步传播到编写正确的复制构造和复制分配、每个异常安全等。
道德:使用标准容器,如vector
、list
或deque
(还有更多)。
//////////////////
foo* f = new foo[iCount];
foo
如果在分配 first 和 last 之间抛出异常,这至少会破坏每个构造的foo
。
当然,您必须注意f
将被正确删除,特别是如果执行此分配的代码还有其他抛出点。
道德:使用标准容器。乍一看,手动内存管理似乎微不足道,尤其是如果您来自 C 语言,但编写异常安全代码并非易事且至关重要。