📜  C++ 中的动态内存(1)

📅  最后修改于: 2023-12-03 14:59:48.413000             🧑  作者: Mango

C++ 中的动态内存

在面向对象的程序设计语言中,内存是一个至关重要的资源。使用静态内存分配可以确保我们的代码在运行过程中一直具有可预测的行为,但是它也有一些劣势,例如无法管理未知大小的数据结构或动态创建对象。

C++ 提供了一种动态分配内存的机制,使程序能够更加灵活地处理变化的内存需求。本文将介绍 C++ 中的动态内存分配方式,包括使用 newdelete 运算符手动管理内存,以及如何使用智能指针自动进行内存管理,以避免不必要的内存泄漏或空指针异常。

使用 new 和 delete 运算符

C++ 中,使用 new 运算符可以在堆(heap)中动态地分配内存。例如,可以使用以下语法在堆中分配一个 int 类型的数值,并返回指向该内存地址的指针:

int *numPtr = new int;

使用 new 运算符分配的内存大小在运行时确定。因此,可以根据程序在运行时的需要动态分配内存,而不必提前知道要分配的内存大小。

使用 new 运算符分配的内存需要手动释放。可以使用 delete 运算符来释放分配的内存:

delete numPtr;

如果没有释放 new 运算符分配的内存,将导致内存泄漏。

除了分配单个对象之外,new 运算符还允许动态分配数组。例如,以下代码可以在堆中分配一个整数数组,并返回指向该数组的指针:

int *arrPtr = new int[10];

使用 new 运算符分配的数组需要使用 delete[] 运算符进行释放:

delete[] arrPtr;

同样地,如果没有释放 new 运算符分配的数组,将导致内存泄漏。

使用智能指针

手动管理内存需要开发人员自己负责及时释放分配的内存,否则可能会导致内存泄漏。而智能指针是 C++ 提供的一种自动化内存管理的机制,可以使代码更加简洁和安全。当智能指针超出范围时,它会自动释放分配的内存,避免了代码中的手动内存管理错误。

C++ 中有三种主要类型的智能指针:std::unique_ptrstd::shared_ptrstd::weak_ptr。以下将介绍其中两种。

std::unique_ptr

std::unique_ptr 允许程序员拥有一个对象,并且在对象被销毁时自动释放分配的内存。与手动管理内存相比,它的优点在于可以自动释放内存,因此不易出现内存泄漏和悬挂指针的问题。以下是一些使用 std::unique_ptr 的例子:

分配单个对象:

std::unique_ptr<int> numPtr(new int);

分配数组:

std::unique_ptr<int[]> arrPtr(new int[10]);

由于 std::unique_ptr 对象所拥有的内存不能被复制,因此它适用于以下情况:

  • 在函数中传递一个对象的所有权。
  • 在一个已知的作用域内分配一个对象的内存。
std::shared_ptr

std::shared_ptr 允许程序员共享一个对象,并且在对象没有任何引用时自动释放分配的内存。它实现了一个引用计数机制,以便在所有引用都被删除后,自动调用 delete 函数来释放内存。以下是一些使用 std::shared_ptr 的例子:

分配单个对象:

std::shared_ptr<int> numPtr(new int);

分配数组:

std::shared_ptr<int[]> arrPtr(new int[10]);

由于 std::shared_ptr 对象所拥有的内存可以被多个指针共享,因此它适用于以下情况:

  • 一个对象需要被多个对象所使用。
  • 在函数间传递对象的所有权,不需要了解对象何时被销毁。
总结

本文介绍了 C++ 中的动态内存分配方式,包括手动管理内存和使用智能指针自动进行内存管理。手动管理内存需要程序员自行管理内存的释放,但是在一些特定的程序场景下可以提供最大的灵活性。智能指针则可以降低内存管理的复杂度,尤其对于快节奏的开发环境和要求高可靠性的程序有重要意义。