文章

C++动态内存

C++动态内存

C++动态内存

C++ 中的动态内存是指在运行时(而不是编译时)根据程序需要分配和释放内存的机制。与静态内存(如栈上分配的变量)相比,动态内存可以提供更大的灵活性,但也更容易出错(如内存泄漏、悬挂指针等)。

堆 vs 栈

方面栈(Stack)堆(Heap)
分配方式编译器自动分配程序员手动分配(new/malloc
生命周期随函数调用自动创建/销毁手动控制(delete/free),或智能指针
分配速度非常快较慢
空间大小较小(几 MB)较大(系统最大空闲内存)
访问效率较低(需要通过指针访问)
释放风险自动释放,几乎无内存泄漏风险易发生泄漏、悬挂指针等问题
使用场景临时变量、函数参数大量数据、对象生命周期不确定

动态内存的基本方式

newdelete,这是 C++ 中分配和释放动态内存的核心操作。

  • 单个对象
1
2
3
int* p = new int(10);   // 分配一个 int,并初始化为 10
std::cout << *p << std::endl;
delete p;               // 释放内存
  • 数组
1
2
3
int* arr = new int[5];  // 分配一个 int 数组,大小为 5
for (int i = 0; i < 5; ++i) arr[i] = i;
delete[] arr;           // 释放数组(注意使用 delete[])

⚠️ 使用 new 分配的内存,不会自动释放,需要显式调用 delete

与 malloc/free 对比

  • new 是一个 运算符,在分配内存后还会调用构造函数。

  • malloc 是一个 函数,只负责分配原始内存,不调用构造函数。

  • delete 会调用析构函数并释放内存,free 只释放内存。

1
2
3
4
5
6
7
8
class MyClass {
public:
    MyClass() { std::cout << "Constructor\n"; }
    ~MyClass() { std::cout << "Destructor\n"; }
};

MyClass* obj = new MyClass(); // 调用构造函数
delete obj;                   // 调用析构函数

常见问题与错误

1. 内存泄漏

1
2
int* p = new int(42);
// 没有 delete p; => 内存泄漏

2. 重复释放(double free)

1
2
3
int* p = new int(5);
delete p;
delete p;  // ❌ 未将 p 置为 nullptr,重复释放

重复释放会导致什么?

  1. 程序崩溃(最常见)

释放一块已释放的内存是未定义行为,可能会:

  • 立即崩溃(如触发段错误 Segmentation Fault);
  • 或运行时出现 “** Error in ./a.out: double free or corruption **” 等错误。
  1. 隐蔽的 bug

有些平台上可能“看起来”没出错,但其实破坏了堆结构,以后某处才崩溃,更难调试。

  1. 被利用为安全漏洞

攻击者可利用 double free 篡改内存管理结构,造成堆溢出攻击、远程代码执行(RCE) 等严重后果。

3. 忘记使用 delete[] 释放数组

1
2
int* arr = new int[10];
delete arr;    // ❌ 未使用 delete[],行为未定义

使用智能指针(推荐做法)

1. std::unique_ptr

自动释放资源,不能共享所有权。

1
2
#include <memory>
std::unique_ptr<int> p = std::make_unique<int>(10);

2. std::shared_ptr

可以共享所有权,最后一个引用析构时释放资源。

1
2
3
#include <memory>
std::shared_ptr<int> p1 = std::make_shared<int>(20);
std::shared_ptr<int> p2 = p1;

3. std::weak_ptr

不增加引用计数,用于解决循环引用。

动态二维数组的分配与释放

1
2
3
4
5
6
7
8
9
10
int rows = 3, cols = 4;
int** matrix = new int*[rows];
for (int i = 0; i < rows; ++i)
    matrix[i] = new int[cols];

// 使用 matrix[i][j]...

for (int i = 0; i < rows; ++i)
    delete[] matrix[i];
delete[] matrix;
本文由作者按照 CC BY 4.0 进行授权