Tutorial Study Image

C++ 中的动态内存


2023年6月12日, Learn eTutorial
675

编程情况经常涉及动态数据或输入,其中数据项的数量会随着程序的运行而变化。一个实际的例子是为公司处理员工列表的应用程序。当姓名添加到列表时,列表会扩展;当姓名从列表中删除时,列表会收缩。内存会为列表分配空间以适应额外的​​数据项,因为姓名会变长。在这种情况下,程序员需要使用动态内存管理策略。

在程序执行之前,所有内存需求都通过声明所需的变量来确定。然而,在某些情况下,程序的内存需求可能只在运行时才知道。例如,当所需的内存量由用户输入决定时。在这些情况下,程序必须动态分配内存,这就是 C++ 语言内置支持 `new` 和 `delete` 运算符的原因。本文介绍了 C++ 中的动态内存分配。

C++ 内存分配

内存分配是为程序中的变量、结构体和类实例指定内存空间的过程。程序执行时会分配内存。`new` 运算符用于分配内存,而 `delete` 运算符用于释放内存。

对于 C++ 程序,内存架构包括:

  • 代码段:这是编译后的程序和执行指令存储的地方。它只能读取。代码段存储在栈和堆下方,以防止覆盖这两个结构。
  • 数据段:这是全局变量和静态变量存储的地方。它不是只读的。
  • 栈:栈通常是预分配的内存。栈是一种后进先出的数据结构。每个新变量都会添加到栈中。当变量超出其作用域时,内存就会被释放。一旦释放,栈变量所占用的内存空间就可以被其他变量使用。函数会推入和弹出局部变量,这会导致栈的扩展和收缩。它保存局部信息、返回地址、函数传递的参数以及内存的当前状态。

C++ 中的静态内存分配

在静态内存分配中,内存由编译器独立分配和释放。在编译时,我们必须指定所需的内存量。编译器在静态内存分配期间确定这些变量需要多少内存,并为其存储固定一个位置。将要存储的变量的位置使用表格保存。但是,在编译时不会为变量分配任何物理内存。

C++ 中的动态内存分配

内存是在程序运行期间动态分配的。但是,在这种情况下,当不再需要动态分配的内存时,由程序员负责释放它。否则,会发生内存泄漏。在程序运行时,程序员可以动态分配存储空间,但他们无法“即时”发明新的变量名,因此动态分配需要满足两个要求:

  • 构建动态内存空间
  • 将其地址保存在指针中(以便可以轻松访问该空间)

内存释放是这个概念的另一个方面,其中为变量或其他数据存储“清理”空间。程序员负责释放动态生成的空间。我们使用 `delete` 运算符来释放动态内存。或者,“动态内存分配”一词指的是手动管理动态内存分配的内存。

理解 C++ 内存泄漏

内存泄漏是由不正确的内存分配和释放实践引起的。最常见的是,它发生在动态内存分配时。因为 C++ 不像 Java 那样具有自动垃圾回收功能,所以程序员负责分配指针所需的内存。

内存泄漏的一个真实世界示例是酒店电梯的滥用。假设您租住在一栋 19 层高的公寓楼里。您想去 10 楼,于是按下了按钮召唤电梯。20 分钟以来,电梯的状态一直显示为地下室。当您调查时,您发现孩子们在地下室玩耍并堵住了电梯入口。然后您意识到有些地方不对劲。

同样,指针在完成其操作后应释放其使用的内存。这样内存就可以被其他变量适当地管理和使用。

可以使用 `delete` 关键字删除已分配的内存。

数组的动态内存分配

如果您(程序员)想为一个 40 个字符的字符串分配内存,那是一个字符数组。下一个示例展示了程序员如何使用相同的技术动态分配内存。


char* val  = NULL;       // Pointer initialized with NULL value
val = new char[40];     // Request memory for the variable
 

使用构造函数的动态分配程序


#include <iostream>
using namespace std; 

class stud {
public:
    stud()
    {
        cout << "Constructor Used" << endl;
    }
    ~stud()
    {
        cout << "Destructor Used" << endl;
    }
};

int main()
{
    stud* S = new stud[6];
    delete[] S;
}

 

输出


Constructor Used
Constructor Used
Constructor Used
Destructor Used
Destructor Used
Destructor Used

动态内存分配的用途

  • 有时存储某些数据所需的内存量是未知。我们可以通过动态内存分配在运行时分配可变大小的内存。
  • 它为程序员提供了灵活性。程序员可以根据需要分配和释放内存。

对于 C 中的动态内存分配,我们使用 `calloc()` 和 `malloc()` 方法。使用 `free()`,我们可以释放该内存。C++ 也支持这些函数。但是,在 C++ 中不鼓励使用这些函数。

C++ 中的 `new` 和 `delete` 这两个一元运算符能够有效地进行动态内存分配和释放。

C++ 中数组的动态内存分配

数组的大小通常在运行时才已知。在这种情况下,动态内存分配非常有用。它提高了内存管理效率。

为数组分配内存块的语法:


pointer_variable = new data_type[size];
 

语法:如果多维数组大小为 m x n


pointer_variable = new data_type[m][n];
 

以下语法将释放任何数组的内存空间:


delete [ ] pointer_variable;
 

一个非常简单的动态内存分配示例,主要针对数组。


#include <iostream>
using namespace std;

int main() {
  int *ptr = new(nothrow) int[20];
  
  if(!ptr){
      cout<<"Sorry Failed! Memory not available."<<endl;
      exit(1);
  }
  
  for(int i=0; i<20; i++){
      ptr[i]=i+1;
  }
  
  for(int i=0; i<20; i++){
      cout<<ptr[i]<<" ";
  }
  
  delete [] ptr;
  return 0;
}

 

输出


1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20