C++ 动态内存
-
动态内存
充分了解动态内存在C++中的实际工作方式对于成为一名优秀的C++程序员至关重要。您的C++程序中的内存分为两部分-- 栈 -函数内部声明的所有变量将占用栈中的内存。
- 堆 -这是程序的未使用内存,可用于在程序运行时动态分配内存。
很多时候,您不会事先知道将特定信息存储在定义的变量中需要多少内存,并且可以在运行时确定所需内存的大小。您可以使用C++中的特殊运算符在运行时为给定类型的变量在堆中分配内存,该运算符返回分配的空间的地址。该运算符称为新运算符。如果不再需要动态分配的内存,则可以使用delete运算符,该运算符将取消分配由new运算符先前分配的内存。 -
new和delete运算符
以下是通用语法,可使用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); }
C语言中的malloc()函数仍然存在于C++中,但是建议避免使用malloc()函数。与malloc()相比,new的主要优点是new不仅分配内存,而且还构造了对象。这是C++的主要目的。无论何时,当您感觉不再需要动态分配的变量时,都可以使用“delete”运算符释放它在免费存储区中占用的内存,如下所示: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对象的数组,则将简单调用构造函数四次,并在删除这些对象时类似地将其调用相同次数。如果我们编译并运行以上代码,这将产生以下结果-Constructor called! Constructor called! Constructor called! Constructor called! Destructor called! Destructor called! Destructor called! Destructor called!