智能指针其实本质是一个模板类,一般使用是用的这个类的对象,而不是指针
智能指针体现在内存释放问题,用智能指针管理new的对象,不需要手动delete
1、唯一指针std::unique_ptr<T>
独占资源所有权的指针。
(1)使用 std::unique_ptr 自动管理内存
{
std::unique_ptr<int> uptr = std::make_unique<int>(200);
//...
// 离开 uptr 的作用域的时候自动释放内存
}
(2)std::unique_ptr 是 move-only 的
{
std::unique_ptr<int> uptr = std::make_unique<int>(200);
std::unique_ptr<int> uptr1 = uptr; // 编译错误,std::unique_ptr<T> 是 move-only 的
std::unique_ptr<int> uptr2 = std::move(uptr);
assert(uptr == nullptr);
}
2、共享指针std::shared_ptr<T>
共享资源所有权的指针。
shared_ptr 需要维护的信息有两部分:
(1)指向共享资源的指针
(2)引用计数等共享资源的控制信息——实现上是维护一个指向控制信息的指针。
简单实现共享指针
template<typename T>
class shared_ptr
{
private:
T* _ptr;
int* _count;//共享引用计数,必须使用指针
public:
//构造函数
shared_ptr(T* ptr = nullptr) : _ptr(ptr)
{
if (_ptr)
{
_count = new int(1);
}
else
{
_count = new int(0);
}
}
//拷贝构造
shared_ptr(const shared_ptr& ptr)
{
if (this != &ptr)
{
this->_ptr = ptr._ptr;
this->_count = ptr._count;
//引用计数+1
(*this->_count)++;
}
}
//重载operator=
shared_ptr& operator=(const shared_ptr& ptr)
{
if (this->_ptr == ptr._ptr)
{
return *this;
}
if (this->_ptr)
{
(*this->_count)--;
if (*this->_count == 0)
{
delete this->_ptr;
delete this->_count;
}
}
this->_ptr = ptr._ptr;
this->_count = ptr._count;
(*this->_count)++;
return *this;
}
//重载operator*
T& operator*()
{
if (this->_ptr)
{
return *(this->_ptr);
}
}
//重载operator->
T* operator->()
{
if (this->_ptr)
{
return this->_ptr;
}
}
//析构函数
~shared_ptr()
{
(*this->_count)--;
if (*this->_count == 0)
{
delete this->_ptr;
delete this->_count;
}
}
//引用计数
int use_count()
{
return *this->_count;
}
};
3、弱引用指针std::weak_ptr<T>
共享资源的观察者,需要和 std::shared_ptr 一起使用,不影响资源的生命周期。
注意事项:
(1)弱引用指针,不会累计引用计数
(2)weak_ptr只能通过shared_ptr或者weak_ptr来构造
(3)主要应用场景:为了解决shared_ptr循环引用,导致内存无法释放问题
(4)通过成员函数lock获取shared_ptr对象,然后再访问数据
shared_ptr循环引用:
class A
{
public:
A() {};
~A() {};
std::shared_ptr<B> b;
private:
};
class B
{
public:
B() {};
~B() {};
std::shared_ptr<A> a;
private:
};
int main()
{
//循环引用,无法析构
std::shared_ptr<A> ptr_a = std::make_shared<A>();
std::shared_ptr<B> ptr_b = std::make_shared<B>();
ptr_a->b = ptr_b;
ptr_b->a = ptr_a;
return 1;
}
网友评论