C++ 智能指针

C++ 智能指针是 C++11 引入的一种资源管理机制,用于自动管理动态分配的内存,减少手动内存管理的复杂性和内存泄漏的风险。智能指针是一个类模板,它通过封装指针,并在指针不再使用时自动释放其所指向的资源,从而避免了显式调用 delete。

C++ 标准库提供了三种主要的智能指针:

  • std::unique_ptr:独占所有权的智能指针。
  • std::shared_ptr:共享所有权的智能指针。
  • std::weak_ptr:观察 shared_ptr 所指向对象的智能指针,但不影响对象的引用计数。

1. std::unique_ptr

std::unique_ptr 是一种独占所有权的智能指针,意味着同一时刻只能有一个 unique_ptr 指向某个对象。unique_ptr 在超出作用域时会自动释放它所管理的内存。

特性:

  • 不可以复制,只有移动。
  • 当 unique_ptr 被销毁时,它会自动释放资源。
cpp 复制代码
#include <iostream>
#include <memory>

class MyClass {
public:
    MyClass() { std::cout << "MyClass Constructor\n"; }
    ~MyClass() { std::cout << "MyClass Destructor\n"; }
};

int main() {
    // 创建一个 unique_ptr,管理一个 MyClass 对象
    std::unique_ptr<MyClass> ptr1 = std::make_unique<MyClass>();

    // 使用 std::move 转移所有权
    std::unique_ptr<MyClass> ptr2 = std::move(ptr1);

    // ptr1 现在为空,ptr2 拥有 MyClass 对象的所有权

    return 0; // 当 ptr2 超出作用域时,MyClass 会被销毁
}

输出:

bash 复制代码
MyClass Constructor
MyClass Destructor

2. std::shared_ptr

std::shared_ptr 是一种共享所有权的智能指针,可以在多个 shared_ptr 对象之间共享对同一个资源的所有权。当最后一个 shared_ptr 被销毁时,资源才会被释放。

特性:

  • 支持多个 shared_ptr 共同拥有一个资源。
  • 使用引用计数来跟踪有多少个 shared_ptr 拥有这个资源,只有引用计数为零时才会释放资源。
cpp 复制代码
#include <iostream>
#include <memory>

class MyClass {
public:
    MyClass() { std::cout << "MyClass Constructor\n"; }
    ~MyClass() { std::cout << "MyClass Destructor\n"; }
};

int main() {
    // 创建一个 shared_ptr,管理一个 MyClass 对象
    std::shared_ptr<MyClass> ptr1 = std::make_shared<MyClass>();

    // 共享所有权
    std::shared_ptr<MyClass> ptr2 = ptr1;

    std::cout << "Use count: " << ptr1.use_count() << std::endl; // 输出当前引用计数

    return 0; // 当 ptr1 和 ptr2 都超出作用域时,MyClass 会被销毁
}

输出:

bash 复制代码
MyClass Constructor
Use count: 2
MyClass Destructor

3. std::weak_ptr

std::weak_ptr 是一种不影响对象引用计数的智能指针。它通常与 std::shared_ptr 一起使用,用于避免循环引用问题。weak_ptr 只是一个观察者,它不会增加引用计数。

特性:

  • 不会影响引用计数。
  • 可以从 weak_ptr 获取一个 shared_ptr,但只有在对象依然存在时才能成功获取。
cpp 复制代码
#include <iostream>
#include <memory>

class MyClass {
public:
    MyClass() { std::cout << "MyClass Constructor\n"; }
    ~MyClass() { std::cout << "MyClass Destructor\n"; }
};

int main() {
    std::shared_ptr<MyClass> ptr1 = std::make_shared<MyClass>();

    // 创建一个 weak_ptr,观察 ptr1
    std::weak_ptr<MyClass> weakPtr = ptr1;

    // 检查 weak_ptr 是否指向有效的对象
    if (auto ptr2 = weakPtr.lock()) {
        std::cout << "weak_ptr is valid\n";
    } else {
        std::cout << "weak_ptr is expired\n";
    }

    return 0; // 当 ptr1 超出作用域时,MyClass 会被销毁
}

输出:

bash 复制代码
MyClass Constructor
weak_ptr is valid
MyClass Destructor

为什么使用智能指针?

  • 自动内存管理: 智能指针通过 RAII(资源获取即初始化)模式管理资源,避免了手动释放内存时可能产生的错误(如忘记释放内存、重复释放等问题)。

  • 避免内存泄漏: 使用 std::unique_ptr 和 std::shared_ptr 可以自动管理内存,避免内存泄漏。

  • 防止悬挂指针和野指针: 智能指针可以保证在指向对象的智能指针被销毁后,该对象的内存被- 自动释放,避免了悬挂指针的风险。

  • 简化代码: 智能指针使得代码更加简洁,减少了内存管理相关的错误,提高了程序的健壮性。

总结

  • std::unique_ptr:独占所有权,不能复制,只能移动。
  • std::shared_ptr:共享所有权,引用计数管理内存。
  • std::weak_ptr:不增加引用计数,避免循环引用。
    智能指针是现代 C++ 编程的重要组成部分,它简化了内存管理并提高了程序的安全性和稳定性。如果你正在进行 C++ 开发,智能指针应该是你代码中不可或缺的工具之一。