weak_ptr,可以访问,但没有所有权
std::shared_ptr<int> sp(new int);
std::weak_ptr<int> wp(sp); // 弱持有,持有者不强依赖weak_ptr所指的对象,可实现解耦。
weak_ptr<T>
模板类没有重载*
和->
运算符,因此weak_ptr
类型指针只能访问某一shared_ptr
指针指向的堆内存空间,无法对其进行修改。
cout << *(wp.lock()) << endl; //借助lock()函数,返回一个和wp同指向的shared_ptr类型指针,获取其存储的数据。
使用场景:想使用对象,但是并不想管理对象,并且在需要使用对象时可以判断对象是否还存在。
观察模式中,subject不控制其观察者的生存期,因此应该是持有观察者的weak_ptr指针。在subject的使用某个指针时,可以先确定是否空悬。
解决空悬指针,循环引用问题;
成员函数
成员方法 |
功能 |
---|---|
operator=() | 重载= 赋值运算符,weak_ptr 指针可以直接被weak_ptr 或者shared_ptr 类型指针赋值。 |
swap(x) | 其中x 表示一个同类型的weak_ptr 类型指针,该函数可以互换2个共同类型weak_ptr 指针的内容。 |
reset() | 将当前weak_ptr 指针置为空指针。 |
use_count() | 查看指向和当前weak_ptr 指针相同的shared_ptr 指针的数量。 |
expired() | 判断当前weak_ptr 指针是否过期(指针为空,或者指向的堆内存已经被释放)。 |
lock() | 原子操作,如果当前weak_ptr 已经过期,则该函数会返回一个空的shared_ptr 指针;反之,该函数返回一个和当前weak_ptr 指针指向相同的shared_ptr 指针。 |
unique_ptr,独占所有权
std::unique_ptr<int> p4(new int);
std::unique_ptr<int> p5(p4);//错误,堆内存不共享
std::unique_ptr<int> p5(std::move(p4));//正确,调用移动构造函数
int * p = p5.release(); //p5 is nullptr
*p = 10
std::unique_ptr<int> p6; p6.reset(p); //p6 is 10
p5 将获取 p4 所指堆空间的所有权,而 p4 将变成空指针(nullptr)
成员函数
成员函数名 |
功 能 |
---|---|
成员函数名 |
功 能 |
operator*() | 获取当前 unique_ptr 指针指向的数据。 |
operator->() | 重载 -> 号,当智能指针指向的数据类型为自定义的结构体时,通过 -> 运算符可以获取其内部的指定成员。 |
operator =() | 重载了 = 赋值号,从而可以将 nullptr 或者一个右值 unique_ptr 指针直接赋值给当前同类型的 unique_ptr 指针。 |
operator []() | 重载了 [] 运算符,当 unique_ptr 指针指向一个数组时,可以直接通过 [] 获取指定下标位置处的数据。 |
get() | 获取当前 unique_ptr 指针内部包含的普通指针。 |
get_deleter() | 获取当前 unique_ptr 指针释放堆内存空间所用的规则。 |
operator bool() | unique_ptr 指针可直接作为 if 语句的判断条件,以判断该指针是否为空,如果为空,则为 false;反之为 true。 |
release() | 释放当前 unique_ptr 指针对所指堆内存的所有权,但该存储空间并不会被销毁。 |
reset(p) | 其中 p 表示一个普通指针,如果 p 为 nullptr,则当前 unique_ptr 也变成空指针;反之,则该函数会释放当前 unique_ptr 指针指向的堆内存(如果有),然后获取 p 所指堆内存的所有权(p 为 nullptr)。 |
swap(x) | 交换当前 unique_ptr 指针和同类型的 x 指针。 |
除此之外,C++11标准还支持同类型的 unique_ptr 指针之间,以及 unique_ptr 和 nullptr 之间,做 ==,!=,<,<=,>,>= 运算。
选用原因:1. 自动释放内存;2. 比share_ptr开销小(没有引用计数);3.有删除器,可以用在自定义删除场景。
int socketFd = 10;
std::unique_ptr<int,void(*)(int*)> ip(&socketFd,[](int *fd){close(*fd);});