C++ Dynamic Memory
很好地理解动态内存如何在C ++中真正起作用对于成为一名优秀的C ++程序员至关重要。 C ++程序中的内存分为两部分 -
The stack - 在函数内声明的所有变量将从堆栈中占用内存。
The heap - 这是程序未使用的内存,可用于在程序运行时动态分配内存。
很多时候,您事先并不知道在特定变量中存储特定信息需要多少内存,并且可以在运行时确定所需内存的大小。
您可以使用C ++中的特殊运算符在堆内的运行时为给定类型的变量分配内存,该运算符返回分配的空间的地址。 此运算符称为new运算符。
如果您不再需要动态分配的内存,可以使用delete运算符,它取消分配以前由new运算符分配的内存。
new和delete运算符
以下通用语法使用new运算符为任何数据类型动态分配内存。
new data-type;
这里, data-type可以是任何内置数据类型,包括数组或任何用户定义的数据类型包括类或结构。 让我们从内置数据类型开始。 例如,我们可以定义一个指向double类型的指针,然后请求在执行时分配内存。 我们可以使用new运算符并使用以下语句执行此操作 -
double* pvalue = NULL; // Pointer 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);
}
来自C的malloc()函数仍然存在于C ++中,但建议避免使用malloc()函数。 new over malloc()的主要优点是new不只是分配内存,而是构造C ++主要目的的对象。
在任何时候,当您感觉不再需要动态分配的变量时,您可以使用'delete'运算符释放它在免费存储中占用的内存,如下所示 -
delete pvalue; // Release memory pointed to by pvalue
让我们将上述概念放在上面,并形成以下示例,以显示“新”和“删除”的工作原理 -
#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!