new [] 和 delete[] 调用多少次来分配和释放内存?

How many times do new [] and delete[] make calls to allocate and deallocate memory?

C++中,每使用一次new []或使用delete [],每次分配或释放内存多少次?我的问题更具体地针对在 classes 上使用它们及其各自的构造函数和析构函数。

例如,取下面的class:

#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;
};

现在,假设需要 class 类型的数组,并且使用 new[],如下所示

Cell* cells = new Cell[5];

当这是可执行文件或程序中的 运行 时,我还看到以下内容打印到标准输出:

Cell being made!
Cell being made!
Cell being made!
Cell being made!
Cell being made!

随后在 cells 指针上调用 delete[] 时,我看到:

Cell being freed!
Cell being freed!
Cell being freed!
Cell being freed!
Cell being freed!

我的问题是,在每次构造函数调用中,内存大小是否等于分配的一个 class 实例?比如new Cell[5]分配内存5次?或者它是否分配一次然后像函数调用一样对构造函数进行 5 次调用?与 delete[] 相同,它是否在每次析构函数调用时释放?

如果(关键字而不是运算符)new [] 成功,它会分配一个足够大的块来容纳所有对象,然后将对象构造到该块中。 同样,(关键字)delete [] 将为数组中的每个对象调用析构函数,然后释放整个块。

new 和 delete(以及 new [] 和 delete[])运算符执行实际的 allocation/deallocation 并且将在 new/new[] 和 [= 的任何给定使用中被调用一次16=][]个关键字。

您正在混合两个不同的概念:

  1. 内存allocation/deallocation
  2. 对象construction/destruction

newdelete 都为我们做了。

new Cell[5];

所有 5 个对象所需的总内存是在单个内存分配操作中分配的。它不能是 5 个分配,因为 5 个不同的分配不能保证连续的空间。

为5个对象分配内存后,new必须通过调用默认构造函数来初始化5个对象。这里我们有 5 个单独的构造函数调用。

delete [] cells 期间发生了类似的事情。它必须通过调用 5 个不同对象的析构函数来销毁 5 个对象。然后所有分配的内存在一次释放操作中被释放。

指令Cell* cells = new Cell[5];意味着你创建了5个连续的Cell对象,它们位于Heap区(主存)。而 cells 是一个位于堆栈区域(主内存)的指针,指向对象( cells 将只存储第一个对象的地址)。之后,每个对象都会调用默认构造函数来初始化它的值,所以你会看到 5 行 Cell being made!.

当您不想使用这些对象并想从堆内存中释放它时,您必须使用 delete [] cells 指令。然后,cells 指向的 5 个对象会调用 5 个析构函数在对象从内存中删除之前做一些事情,但是 cells 仍然存在于 Stack 内存中,它可以用来指向另一个 Cell 对象(只有当 cells 超出其范围时, cells 才会从区域中删除,现在堆内存中只有 5 个对象被删除)。所以你可以看到 5 行 Cell being freed!