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 被销毁时,它会自动释放资源。
#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 会被销毁
}
输出:
MyClass Constructor
MyClass Destructor
2. std::shared_ptr
std::shared_ptr 是一种共享所有权的智能指针,可以在多个 shared_ptr 对象之间共享对同一个资源的所有权。当最后一个 shared_ptr 被销毁时,资源才会被释放。
特性:
- 支持多个 shared_ptr 共同拥有一个资源。
- 使用引用计数来跟踪有多少个 shared_ptr 拥有这个资源,只有引用计数为零时才会释放资源。
#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 会被销毁
}
输出:
MyClass Constructor
Use count: 2
MyClass Destructor
3. std::weak_ptr
std::weak_ptr 是一种不影响对象引用计数的智能指针。它通常与 std::shared_ptr 一起使用,用于避免循环引用问题。weak_ptr 只是一个观察者,它不会增加引用计数。
特性:
- 不会影响引用计数。
- 可以从 weak_ptr 获取一个 shared_ptr,但只有在对象依然存在时才能成功获取。
#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 会被销毁
}
输出:
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++ 开发,智能指针应该是你代码中不可或缺的工具之一。