很好地理解动态内存在C ++中的实际运行方式对于成为优秀的C ++程序员至关重要. C ++程序中的内存分为两部分 :
堆栈 : 在函数内声明的所有变量都将从堆栈中占用内存.
堆 : 这是程序未使用的内存,可用于在程序运行时动态分配内存.
很多时候,你不知道事先确定在定义的变量中存储特定信息需要多少内存,并且可以在运行时确定所需内存的大小.
您可以在堆内的运行时分配内存对于给定类型的变量,使用C ++中的特殊运算符返回分配的空间的地址.此运算符称为 new 运算符.
如果您不再需要动态分配的内存,可以使用 delete 运算符,取消分配以前由新运算符分配的内存.
new和delete运算符
使用以下通用语法 new 运算符为任何数据类型动态分配内存.
new data-type;
这里, data-type 可以是任何内置数据类型,包括数组或任何用户定义的数据类型包括类或结构体.让我们从内置数据类型开始.例如,我们可以定义一个指向double类型的指针,然后请求在执行时分配内存.我们可以使用 new 运算符使用以下语句 :
double* pvalue = NULL; // Pointer initialized with nullpvalue = new double; // Request memory for the variable
如果免费商店已用完,内存可能尚未成功分配.因此,最好检查新运算符是否返回NULL指针并采取适当的操作,如下所示;
double* pvalue = NULL;if( !(pvalue = new double )) { cout << "Error: out of memory." <C中的 malloc()函数仍然存在于C ++中,但建议避免使用malloc()函数. new over malloc()的主要优点是new不只是分配内存,而是构造C ++主要目的的对象.
在任何时候,当你感觉到变量时已经动态分配不再需要了,您可以使用'delete'运算符释放它在免费商店中占用的内存,如下所示 :
delete pvalue; // Release memory pointed to by pvalue让我们将上述概念放在上面,并形成以下示例,以显示'new'和'delete'是如何工作的?
#includeusing 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 : 29495Dynamic Memory Allocation for Arrays
考虑要为一个字符数组(即20个字符的字符串)分配内存。 使用与上面相同的语法,可以动态分配内存,如下所示。
char* pvalue = NULL; // Pointer initialized with nullpvalue = 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 pvalueDynamic Memory Allocation for Objects
对象与简单数据类型没有什么不同。 例如,考虑下面的代码,我们将使用对象数组来阐明概念:
#includeusing namespace std;class Box { public: Box() { cout << "Constructor called!" < 如果要分配一个包含四个Box对象的数组,则将简单调用构造函数四次,并在删除这些对象时类似地将其调用相同次数。
如果我们编译并运行以上代码,这将产生以下结果:
Constructor called!Constructor called!Constructor called!Constructor called!Destructor called!Destructor called!Destructor called!Destructor called!