1. unique_ptr、shared_ptr 和 weak_ptr 的资源管理机制
- unique_ptr:
- 内存释放:采用独占式拥有资源的方式,当 unique_ptr 对象被销毁时(例如离开其作用域),它所管理的资源会自动被释放。这是通过在 unique_ptr 的析构函数中调用 delete 操作符来实现的。
- 引用计数:没有引用计数概念,因为它不允许多个 unique_ptr 同时指向同一个资源。
- shared_ptr:
- 内存释放:使用引用计数来管理资源。当一个 shared_ptr 对象创建并指向一个资源时,引用计数初始化为 1。每当有新的 shared_ptr 指向该资源(例如通过拷贝构造函数或赋值操作符),引用计数加 1。当一个 shared_ptr 对象被销毁(例如离开其作用域),引用计数减 1。当引用计数降为 0 时,表明没有任何 shared_ptr 再指向该资源,此时资源会被自动释放,通常是调用 delete 操作符。
- 引用计数:内部维护一个引用计数变量,用于记录指向该资源的 shared_ptr 对象的数量。
- weak_ptr:
- 内存释放:不参与资源的直接管理和引用计数的增减。它主要用于解决 shared_ptr 相互引用导致的循环引用问题。weak_ptr 指向由 shared_ptr 管理的对象,但不增加引用计数。当指向的对象的 shared_ptr 引用计数变为 0 并释放资源时,weak_ptr 会自动变为空指针。
- 引用计数:不影响指向对象的引用计数,它只是一个观察者,用于检测所指向对象是否已被释放。
2. 自定义模仿 shared_ptr 行为的资源管理类关键代码
template <typename T>
class MySharedPtr {
private:
T* ptr;
int* refCount;
public:
// 构造函数
MySharedPtr(T* p = nullptr) : ptr(p) {
if (ptr) {
refCount = new int(1);
} else {
refCount = new int(0);
}
}
// 拷贝构造函数
MySharedPtr(const MySharedPtr& other) : ptr(other.ptr), refCount(other.refCount) {
if (ptr) {
++(*refCount);
}
}
// 赋值操作符
MySharedPtr& operator=(const MySharedPtr& other) {
if (this == &other) {
return *this;
}
release();
ptr = other.ptr;
refCount = other.refCount;
if (ptr) {
++(*refCount);
}
return *this;
}
// 析构函数
~MySharedPtr() {
release();
}
T& operator*() {
return *ptr;
}
T* operator->() {
return ptr;
}
private:
void release() {
if (ptr && --(*refCount) == 0) {
delete ptr;
delete refCount;
}
}
};