了解动态内存在C++中如何工作是成为一个很好的C++程序员必不可少的。C++程序存储器分为两个部分:
-
栈: 在函数内部声明的所有变量都将占用栈内存。
-
堆: 这是程序未使用的存储器,可以用于当程序运行时动态分配的存储器。
很多时候,不知道提前知道需要多少内存,需要存储的特定信息的定义的变量和所需内存的大小可以在运行时才确定。
可以在运行时在堆内分配存储器给定类型的使用特殊的运算符在C++中返回所分配的空间变量的地址。这种运算符被称为new运算符。
如果不需要动态分配的内存,可以使用delete运算符,删除分配内存之前由new运算符分配。
new和delete运算符:
有以下通用语法使用new运算符来动态分配内存任何的数据类型。
new data-type;
这里,数据类型可以是包括数组或定义的数据类型包括类或结构的任何用户的任何内置数据类型。让我们从内置的数据类型。例如,我们可以定义一个指针,指向double类型,然后请求的内存在执行时进行分配。我们可以使用new运算符使用下面的语句做到这一点:
double* pvalue = NULL; // Yiibaier initialized with null pvalue = new double; // Request memory for the variable
存储器可能没有成功地分配,如果自由存储区已被用完。所以这是很好的做法,检查是否有新的操作符返回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操作符释放它占用的内存如下:
delete pvalue; // Release memory yiibaied to by pvalue
让我们把上述概念,并形成以下例子来说明如何利用new 和 delete 来工作:
#include <iostream> using namespace std; int main () { double* pvalue = NULL; // Yiibaier 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; // Yiibaier initialized with null pvalue = new char[20]; // Request memory for the variable
要删除我们刚才创建的声明数组,是这样的:
delete [] pvalue; // Delete array yiibaied to by pvalue
下面的new操作符的类似通用语法,可以分配一个多维数组,如下所示:
double** pvalue = NULL; // Yiibaier initialized with null pvalue = new double [3][4]; // Allocate memory for a 3x4 array
但是,用于多维数组的存储器释放语法将仍然保持与上述相同的:
delete [] pvalue; // Delete array yiibaied 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对象的数组,简单的构造将被调用4次,同样,同时删除这些对象,析构也将被调用次数(4次)相同。
如果我们编译并运行上面的代码,这会产生以下结果:
Constructor called! Constructor called! Constructor called! Constructor called! Destructor called! Destructor called! Destructor called! Destructor called!