C++ 动态内存管理
                           
天天向上
发布: 2025-03-29 17:13:07

原创
141 人浏览过

在 C++ 中,动态内存管理允许在程序运行时分配和释放内存空间。与静态内存分配不同,动态内存分配的内存大小可以根据程序的需要来决定,这为编程提供了更大的灵活性。C++ 提供了两种主要的操作来管理动态内存:newdelete

1. 动态内存分配

1.1 使用 new 操作符

new 操作符用于在堆(heap)上分配内存,并返回指向该内存的指针。与在栈上分配内存不同,堆上的内存可以在整个程序生命周期中访问,直到手动释放。

分配单个对象的内存

#include <iostream>
using namespace std;

int main() {
    int* p = new int;  // 分配一个 int 类型的内存空间
    *p = 5;  // 为这个内存位置赋值
    cout << "Value: " << *p << endl;  // 输出:Value: 5

    delete p;  // 释放内存
    return 0;
}

说明:

  • new int:在堆上分配一个 int 类型的内存空间。
  • delete p:释放之前通过 new 分配的内存。

分配数组的内存

#include <iostream>
using namespace std;

int main() {
    int* arr = new int[5];  // 分配一个包含 5 个整数的数组

    // 给数组赋值
    for (int i = 0; i < 5; ++i) {
        arr[i] = i * 10;
    }

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

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

说明:

  • new int[5]:分配一个包含 5 个整数的动态数组。
  • delete[] arr:释放通过 new[] 分配的数组内存。

1.2 使用 new 返回的指针

当你使用 new 分配内存时,它返回一个指向已分配内存的指针。如果内存分配失败(例如,内存不足),new 会抛出 std::bad_alloc 异常。

#include <iostream>
#include <new>  // 包含 std::bad_alloc
using namespace std;

int main() {
    try {
        int* p = new int[10000000000];  // 尝试分配一个巨大的数组
    }
    catch (const bad_alloc& e) {
        cout << "Memory allocation failed: " << e.what() << endl;
    }

    return 0;
}

说明:

  • std::bad_alloc:如果内存分配失败,new 会抛出此异常。

2. 动态内存释放

在 C++ 中,使用 new 分配的内存必须手动释放,否则会发生内存泄漏(memory leak)。释放内存使用 delete(单个对象)或 delete[](数组)操作符。

2.1 释放单个对象的内存

#include <iostream>
using namespace std;

int main() {
    int* p = new int(10);  // 分配并初始化内存
    cout << "Value: " << *p << endl;  // 输出:Value: 10

    delete p;  // 释放内存
    return 0;
}

2.2 释放数组的内存

#include <iostream>
using namespace std;

int main() {
    int* arr = new int[3] {1, 2, 3};  // 分配并初始化数组

    for (int i = 0; i < 3; ++i) {
        cout << arr[i] << " ";  // 输出:1 2 3
    }
    cout << endl;

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

注意:

  • 使用 delete 时要注意区分单个对象和数组对象。对于数组对象,必须使用 delete[] 来释放内存。

3. C++11 智能指针

C++11 引入了智能指针(std::unique_ptrstd::shared_ptr),这些指针可以自动管理动态分配的内存,从而避免手动管理内存的麻烦。

3.1 std::unique_ptr

std::unique_ptr 是一种智能指针,它确保只有一个指针可以管理某个内存。离开作用域时,std::unique_ptr 会自动释放内存。

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

int main() {
    unique_ptr<int> ptr(new int(10));  // 分配内存并初始化
    cout << "Value: " << *ptr << endl;  // 输出:Value: 10

    // 不需要显式调用 delete,ptr 超出作用域时自动释放内存
    return 0;
}

3.2 std::shared_ptr

std::shared_ptr 是一个智能指针,它允许多个指针共享对同一块内存的所有权。内存会在最后一个指针离开作用域时自动释放。

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

int main() {
    shared_ptr<int> ptr1 = make_shared<int>(20);  // 创建并初始化共享指针
    {
        shared_ptr<int> ptr2 = ptr1;  // ptr1 和 ptr2 共享同一块内存
        cout << "Shared value: " << *ptr2 << endl;  // 输出:Shared value: 20
    }  // ptr2 超出作用域,内存不会立即释放,因为 ptr1 仍然拥有所有权

    // 当 ptr1 超出作用域时,内存才会被释放
    return 0;
}

3.3 智能指针优势

  • 自动内存管理:智能指针能够自动释放内存,避免内存泄漏。
  • 内存共享std::shared_ptr 允许多个对象共享对同一块内存的所有权。

4. 内存泄漏和防止内存泄漏

内存泄漏是指程序分配的内存未能及时释放,导致无法再访问和使用该内存。这会导致程序的内存占用不断增加,最终可能导致程序崩溃。

4.1 内存泄漏的示例

#include <iostream>
using namespace std;

int main() {
    int* p = new int(100);  // 动态分配内存
    // 忘记释放内存,导致内存泄漏
    return 0;
}

解决方案

  • 始终确保在使用完动态内存后使用 deletedelete[] 释放内存。
  • 可以考虑使用智能指针(std::unique_ptrstd::shared_ptr)来管理内存,减少内存泄漏的风险。

5. 总结

  • 动态内存分配:使用 new 操作符来分配内存。
  • 动态内存释放:使用 delete(单个对象)或 delete[](数组)释放内存。
  • 智能指针std::unique_ptrstd::shared_ptr 自动管理动态内存,避免内存泄漏。
  • 内存泄漏:如果动态内存没有释放,就会发生内存泄漏,使用智能指针可以有效防止这种情况。

通过理解并使用 C++ 的动态内存管理功能,你可以更加高效地控制内存的使用和释放,从而提高程序的性能和稳定性。

发表回复 0

Your email address will not be published. Required fields are marked *