在C++
中,每次使用new []
或使用delete []
时,每个内存分配或取消分配多少次?我的问题是更具体地讲,如何在具有各自构造函数和析构函数的类上使用它们。
例如,参加以下课程:
#include <iostream>
class Cell
{
public:
Cell() : _value(2)
{
std::cout << "Cell being made!\n";
}
~Cell()
{
std::cout << "Cell being freed!\n";
}
const int& getVal() const
{
return _value;
}
private:
int _value;
};
现在,说需要一个该类类型的数组,并使用new[]
,如下所示
Cell* cells = new Cell[5];
当它在可执行文件或程序中运行时,我还看到以下内容打印到标准输出:
Cell being made!
Cell being made!
Cell being made!
Cell being made!
Cell being made!
随后在delete[]
指针上调用cells
时,我看到:
Cell being freed!
Cell being freed!
Cell being freed!
Cell being freed!
Cell being freed!
我的问题是,在每个构造函数调用中,内存大小是否等于所分配的一个类实例? new Cell[5]
是否分配5次内存?还是分配一次,然后仅以函数调用的形式对构造函数进行5次调用?与delete[]
一样,它是否在每次析构函数调用时都会释放?
答案 0 :(得分:17)
您正在混合两个不同的概念:
new
和delete
对我们都有帮助。
new Cell[5];
所有5个对象所需的总内存在单个内存分配操作中分配。不能是5个分配,因为5个不同的分配不能保证连续的空格。
为5个对象分配内存后,new
必须通过调用默认构造函数来初始化5个对象。这里我们有5个单独的构造函数调用。
在delete [] cells
期间发生了类似的事情。它必须通过调用5个不同对象的析构函数来销毁5个对象。然后,通过一次重新分配操作释放所有分配的内存。
答案 1 :(得分:0)
如果new [](相对于关键字而不是运算符)new []成功,它将分配一个足以容纳所有对象的块,然后将对象构造到该块中。 同样,(关键字)delete []将为数组中的每个对象调用析构函数,然后重新分配整个块。
new和delete(以及new []和delete [])运算符执行实际的分配/解除分配,并且对于new / new []和delete / delete []关键字的任何给定用法,将被调用一次。 / p>
答案 2 :(得分:0)
指令Cell* cells = new Cell[5];
表示您创建5个连续位于堆区域(主内存)上的单元对象。 cells
是一个位于对象的堆栈区域(指向主对象)上的指针(cells
只会存储第一个对象的地址)。之后,每个对象将调用默认构造函数以初始化其值,因此您将看到5行Cell being made!
。
当您不想使用对象并将其从堆内存中释放时,必须使用delete [] cells
指令。然后,cells
指向的5个对象将在对象从内存中删除之前调用5个析构函数执行某些操作,但是cells
仍存在于堆栈存储器中,并且可以用于指向另一个Cell对象(仅当cells
超出其范围时,cells
才会从区域中删除,现在堆内存上只有5个对象被删除)。这样您可以看到5行Cell being freed!