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=][]个关键字。
您正在混合两个不同的概念:
- 内存allocation/deallocation
- 对象construction/destruction
new
和 delete
都为我们做了。
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!
在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=][]个关键字。
您正在混合两个不同的概念:
- 内存allocation/deallocation
- 对象construction/destruction
new
和 delete
都为我们做了。
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!