- C++ 基础
- C++ 首页
- C++ 概述
- C++ 环境设置
- C++ 基本语法
- C++ 注释
- C++ Hello World
- C++ 省略命名空间
- C++ 常量/字面量
- C++ 关键字
- C++ 标识符
- C++ 数据类型
- C++ 数值数据类型
- C++ 字符数据类型
- C++ 布尔数据类型
- C++ 变量类型
- C++ 变量作用域
- C++ 多个变量
- C++ 基本输入/输出
- C++ 修饰符类型
- C++ 存储类
- C++ 运算符
- C++ 数字
- C++ 枚举
- C++ 引用
- C++ 日期和时间
- C++ 控制语句
- C++ 决策
- C++ if 语句
- C++ if else 语句
- C++ 嵌套 if 语句
- C++ switch 语句
- C++ 嵌套 switch 语句
- C++ 循环类型
- C++ while 循环
- C++ for 循环
- C++ do while 循环
- C++ foreach 循环
- C++ 嵌套循环
- C++ break 语句
- C++ continue 语句
- C++ goto 语句
- C++ 构造函数
- C++ 构造函数和析构函数
- C++ 复制构造函数
C++ 动态内存
深入理解 C++ 中动态内存的工作原理对于成为一名优秀的 C++ 程序员至关重要。C++ 程序中的内存分为两个部分:
栈 - 在函数内部声明的所有变量都将从栈中占用内存。
堆 - 这是程序的未使用内存,可以在程序运行时动态分配内存。
很多时候,您事先并不知道需要多少内存来存储定义变量中的特定信息,并且所需内存的大小可以在运行时确定。
您可以使用 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
如果空闲存储已用完,则内存可能无法成功分配。因此,最好检查 new 运算符是否返回 NULL 指针并采取适当的操作,如下所示:
double* pvalue = NULL; if( !(pvalue = new double )) { cout << "Error: out of memory." <<endl; exit(1); }
来自 C 的malloc()函数仍然存在于 C++ 中,但建议避免使用 malloc() 函数。new 相对于 malloc() 的主要优势在于,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 对象的数组,则 Simple 构造函数将被调用四次,类似地,在删除这些对象时,析构函数也将被调用相同次数。
如果我们编译并运行上述代码,这将产生以下结果:
Constructor called! Constructor called! Constructor called! Constructor called! Destructor called! Destructor called! Destructor called! Destructor called!