C++ 动态内存
深入了解动态内存在 C++ 中的实际工作原理对于成为一名优秀的 C++ 程序员至关重要。 C++ 程序中的内存分为两部分 -
-
堆栈 − 函数内部声明的所有变量都会从堆栈中占用内存。
-
堆 − 这是程序未使用的内存,可用于在程序运行时动态分配内存。
很多时候,您事先并不知道在定义的变量中存储特定信息需要多少内存,而所需内存的大小可以在运行时确定。
您可以在运行时使用 C++ 中的特殊运算符在堆内为给定类型的变量分配内存,该运算符返回已分配空间的地址。此运算符称为 new 运营商。
如果您不再需要动态分配的内存,您可以使用 delete 运算符,它会释放之前由 new 运算符分配的内存。
新建和删除运算符
使用 new 有以下通用语法 运算符为任何数据类型动态分配内存。
new data-type;
这里,数据类型 可以是任何内置数据类型,包括数组或任何用户定义的数据类型,包括类或结构。让我们从内置数据类型开始。例如,我们可以定义一个指向 double 类型的指针,然后请求在执行时分配内存。我们可以使用 new 具有以下语句的运算符 -
double* pvalue = NULL; // Pointer initialized with null pvalue = new double; // Request memory for the variable
如果空闲存储已用完,则内存可能未成功分配。因此,检查 new 运算符是否返回 NULL 指针并采取适当的措施是一种很好的做法,如下所示 -
double* pvalue = NULL; if( !(pvalue = new double )) { cout << "Error: out of memory." <<endl; exit(1); }
malloc() 来自 C 的函数,在 C++ 中仍然存在,但建议避免使用 malloc() 函数。 new 优于 malloc() 的主要优点是 new 不只是分配内存,它构造对象,这是 C++ 的主要目的。
在任何时候,当您觉得不再需要动态分配的变量时,您可以使用“删除”运算符释放它在空闲存储中占用的内存,如下所示 -
delete pvalue; // Release memory pointed to by pvalue
让我们把上面的概念并形成下面的例子来展示“new”和“delete”是如何工作的 -
现场演示#include <iostream> using namespace std; int main () { double* pvalue = NULL; // Pointer initialized with null pvalue = new double; // Request memory for the variable *pvalue = 29494.99; // Store value at allocated address cout << "Value of pvalue : " << *pvalue << endl; delete pvalue; // free up the memory. return 0; }
如果我们编译并运行上面的代码,这将产生以下结果 -
Value of pvalue : 29495
数组的动态内存分配
考虑你想为一个字符数组分配内存,即 20 个字符的字符串。使用我们上面使用的相同语法,我们可以动态分配内存,如下所示。
char* pvalue = NULL; // Pointer initialized with null pvalue = new char[20]; // Request memory for the variable
要删除我们刚刚创建的数组,语句如下所示 -
delete [] pvalue; // Delete array pointed to by pvalue
按照类似 new 运算符的通用语法,您可以为多维数组分配如下 -
double** pvalue = NULL; // Pointer initialized with null pvalue = new double [3][4]; // Allocate memory for a 3x4 array
但是,多维数组释放内存的语法还是和上面一样 -
delete [] pvalue; // Delete array pointed to by pvalue
对象的动态内存分配
对象与简单的数据类型没有什么不同。例如,考虑以下代码,我们将使用对象数组来阐明概念 -
现场演示#include <iostream> using namespace std; class Box { public: Box() { cout << "Constructor called!" <<endl; } ~Box() { cout << "Destructor called!" <<endl; } }; int main() { Box* myBoxArray = new Box[4]; delete [] myBoxArray; // Delete array return 0; }
如果你要分配一个包含四个 Box 对象的数组,Simple 构造函数将被调用四次,同样,在删除这些对象时,析构函数也将被调用相同的次数。
如果我们编译并运行上面的代码,这将产生以下结果 -
Constructor called! Constructor called! Constructor called! Constructor called! Destructor called! Destructor called! Destructor called! Destructor called!
C语言