目录

  1. 动态内存概述
  2. 动态内存分配
  3. 动态内存释放
  4. 使用 newdelete
  5. 使用 new[]delete[]
  6. 内存泄漏和避免内存泄漏
  7. 示例代码
  8. 参考资料

1. 动态内存概述

在 C++ 中,动态内存是指在程序运行时(而不是编译时)通过操作系统分配的内存。动态内存允许程序在运行过程中根据需要分配和释放内存,这使得程序能够灵活地使用内存,并且在需要时释放不再使用的内存。

动态内存通常用于:

  • 存储不确定大小的数组
  • 存储不确定数量的对象
  • 实现数据结构(如链表、树等)

动态内存的分配和释放通常是通过 newdelete 操作符来管理的。


2. 动态内存分配

在 C++ 中,动态内存分配是通过 new 操作符来实现的。new 操作符会在堆(heap)上分配指定大小的内存,并返回指向该内存块的指针。

语法

pointer = new type;  // 分配单个元素
pointer = new type[size];  // 分配数组

  • new type 用于分配单个类型的对象,并返回该对象的指针。
  • new type[size] 用于分配一个指定大小的类型数组,并返回数组的指针。

示例:动态分配一个整数

#include <iostream>
using namespace std;

int main() {
    int* ptr = new int;  // 在堆上分配一个整数
    *ptr = 10;  // 给动态分配的内存赋值
    cout << "Value: " << *ptr << endl;  // 输出值

    delete ptr;  // 释放动态内存
    return 0;
}

在这个示例中,我们使用 new int 在堆上动态分配了一个整数,给它赋值并输出,最后使用 delete 释放该内存。


3. 动态内存释放

动态内存分配后,必须显式地释放内存,否则可能会导致内存泄漏。C++ 使用 delete 操作符来释放通过 new 分配的内存。

语法

delete pointer;  // 释放通过 `new` 分配的单个对象
delete[] pointer;  // 释放通过 `new[]` 分配的数组

  • delete pointer 释放通过 new 分配的单个对象。
  • delete[] pointer 释放通过 new[] 分配的数组。

示例

#include <iostream>
using namespace std;

int main() {
    int* arr = new int[5];  // 动态分配一个数组
    for (int i = 0; i < 5; ++i) {
        arr[i] = i + 1;  // 给数组赋值
    }

    // 输出数组内容
    for (int i = 0; i < 5; ++i) {
        cout << arr[i] << " ";
    }
    cout << endl;

    delete[] arr;  // 释放数组的动态内存
    return 0;
}

在这个示例中,我们使用 new[] 动态分配一个整数数组,并在使用完之后通过 delete[] 释放该数组。


4. 使用 newdelete

在 C++ 中,newdelete 是用于动态内存管理的核心操作符。new 分配内存并返回一个指向该内存块的指针,delete 释放内存。

示例:使用 newdelete 分配和释放对象

#include <iostream>
using namespace std;

class MyClass {
public:
    MyClass() { cout << "Constructor called" << endl; }
    ~MyClass() { cout << "Destructor called" << endl; }
};

int main() {
    MyClass* ptr = new MyClass();  // 动态分配对象
    delete ptr;  // 释放对象

    return 0;
}

在这个示例中,我们通过 new 创建了一个动态对象,并通过 delete 删除了该对象。构造函数和析构函数分别在创建和删除时被调用。


5. 使用 new[]delete[]

当需要动态分配数组时,应该使用 new[] 来分配内存,并使用 delete[] 来释放内存。这样做能正确地释放每个数组元素的资源,避免内存泄漏。

示例:使用 new[]delete[] 分配和释放数组

#include <iostream>
using namespace std;

int main() {
    int* arr = new int[3];  // 动态分配数组
    for (int i = 0; i < 3; ++i) {
        arr[i] = i * 10;  // 给数组赋值
    }

    // 输出数组内容
    for (int i = 0; i < 3; ++i) {
        cout << arr[i] << " ";
    }
    cout << endl;

    delete[] arr;  // 释放数组的动态内存
    return 0;
}

在此示例中,new[] 用于分配一个整数数组,delete[] 用于释放该数组的内存。


6. 内存泄漏和避免内存泄漏

内存泄漏是指程序分配了内存,但没有正确释放,导致内存无法被回收。在 C++ 中,内存泄漏通常由以下原因造成:

  • 忘记调用 deletedelete[]
  • 使用了 newnew[] 后,丢失了指向动态内存的指针。
  • 处理异常时没有正确释放内存。

如何避免内存泄漏:

  1. 总是释放内存:每次通过 new 分配内存后,使用 deletedelete[] 释放它。
  2. 使用智能指针:在 C++11 中,可以使用 std::unique_ptrstd::shared_ptr 来自动管理内存,避免内存泄漏。
  3. 避免野指针:确保指向动态分配内存的指针在内存释放后不再被使用。

7. 示例代码

示例 1:内存泄漏

#include <iostream>
using namespace std;

int main() {
    int* ptr = new int;  // 动态分配内存
    *ptr = 42;

    // 忘记释放内存,会导致内存泄漏
    return 0;
}

示例 2:避免内存泄漏

#include <iostream>
using namespace std;

int main() {
    int* ptr = new int;  // 动态分配内存
    *ptr = 42;

    delete ptr;  // 释放内存,避免内存泄漏
    return 0;
}

示例 3:使用智能指针避免内存泄漏

#include <iostream>
#include <memory>
using namespace std;

int main() {
    // 使用 unique_ptr 自动管理内存
    unique_ptr<int> ptr = make_unique<int>(42);
    cout << *ptr << endl;  // 输出值
    // 无需手动 delete,unique_ptr 会自动释放内存
    return 0;
}


8. 参考资料


总结

C++ 中的动态内存分配提供了灵活的内存管理能力,但同时也需要程序员手动管理内存的分配和释放。使用 newdelete 时,必须确保在不再需要内存时及时释放它,以避免内存泄漏。使用智能指针(如 std::unique_ptrstd::shared_ptr)可以自动管理内存,减少内存泄漏的风险。在开发过程中,注意动态内存的正确管理至关重要。