C++智能指针
C++11 引入了智能指针,以简化内存管理并减少内存泄漏和资源管理错误 智能指针是标准库提供的类模板,用于管理动态分配的对象的生命周期 主要有三种类型的智能指针: std::unique_ptr, std::shared_ptr, std::weak_ptr
智能智能指针是什么?
- 智能指针: 自动管理资源的生命周期,避免内存泄漏和悬空指针
- 所有权管理: 智能指针定义了资源的所有权和生命周期
- RAII(Resource Acquisition Is Initialization): 智能指针利用对象生命周期自动管理资源
std::unique_ptr
std::unique_ptr
是一个独占所有权的智能指针,不允许多个 unique_ptr
实例共享同一个资源
-
特点:
- 独占所有权: 一个
std::unique_ptr
对象负责一个资源的生命周期 - 不允许拷贝:
std::unique_ptr
不能被复制,只能被移动 - 自动释放: 当
unique_ptr
超出作用域时,它会自动释放所管理的资源
- 独占所有权: 一个
-
使用示例:
#include <memory>
void example() {
std::unique_ptr<int> ptr1(new int(10));
// 或使用 make_unique (C++14及以上)
auto ptr2 = std::make_unique<int>(20);
// 不能复制
// std::unique_ptr<int> ptr3 = ptr1; // 错误
// 可以移动
std::unique_ptr<int> ptr4 = std::move(ptr1);
}
std::shared_ptr
std::shared_ptr
是一个共享所有权的智能指针 多个 shared_ptr
实例可以共享对同一个资源的所有权,资源会在最后一个 shared_ptr 被销毁时释放
-
特点:
- 共享所有权: 多个 std::shared_ptr 实例可以共同管理同一个资源
- 引用计数: 每个 shared_ptr 持有一个引用计数,当引用计数为零时,资源会被释放
- 允许拷贝: std::shared_ptr 可以被复制
-
使用示例:
#include <memory>
void example() {
std::shared_ptr<int> ptr1 = std::make_shared<int>(10);
std::shared_ptr<int> ptr2 = ptr1; // 共享所有权
// 资源会在最后一个 shared_ptr 被销毁时释放
}
std::weak_ptr
std::weak_ptr
是一个不改变引用计数的智能指针,用于解决 std::shared_ptr
可能导致的循环引用问题 std::weak_ptr
不会管理资源的生命周期,而是观察 std::shared_ptr
是否仍然存在
-
特点:
- 不改变引用计数: 不会影响 std::shared_ptr 的引用计数
- 用于打破循环引用: 避免 std::shared_ptr 之间的循环引用导致内存泄漏
- 可以通过 lock() 方法获得 std::shared_ptr
-
使用示例:
#include <memory>
#include <iostream>
class Resource {
public:
std::shared_ptr<Resource> other;
};
void example() {
std::shared_ptr<Resource> ptr1 = std::make_shared<Resource>();
std::weak_ptr<Resource> weakPtr = ptr1; // 不影响引用计数
if (auto sharedPtr = weakPtr.lock()) {
std::cout << "Resource is still available.\n";
} else {
std::cout << "Resource has been freed.\n";
}
}
自定义删除器
智能指针支持自定义删除器,以处理资源的特殊释放需求
- std::unique_ptr 自定义删除器:
#include <memory>
#include <iostream>
void customDeleter(int* p) {
std::cout << "Custom deleter called for " << *p << std::endl;
delete p;
}
void example() {
std::unique_ptr<int, decltype(&customDeleter)> ptr(new int(10), customDeleter);
}
- std::shared_ptr 自定义删除器:
#include <memory>
#include <iostream>
void customDeleter(int* p) {
std::cout << "Custom deleter called for " << *p << std::endl;
delete p;
}
void example() {
std::shared_ptr<int> ptr(new int(10), customDeleter);
}
常见错误
- 循环引用:
std::shared_ptr
之间形成循环引用会导致内存泄漏 使用std::weak_ptr
打破循环引用 - 空指针解引用:访问
std::unique_ptr
或std::shared_ptr
的空指针会导致未定义行为