Smart Pointers
This file shows some usages of smart pointers in C/C++
Reference
Reference articles: C++ STL 四种智能指针
std::unique_ptr<T>
旨在代替旧的
auto_ptr需
#include <memory>头文件只能通过移动语义来转移所管理对象的管理权
可以通过
make_unique这个helper函数来构造auto ptrA = std::make_unique<string>("dablelv")
能通过移动语义转移管理权
auto ptrB = std::move(ptrA)
不能赋值到其他
std::unique_ptr不能值传递到函数中(无法作为函数参数,因为要值传递)
不能用于需要副本的
STL算法例外:如果unique_ptr 是个临时右值,编译器允许拷贝语义
基本操作
// 创建空指针 std::unique_ptr<int> u_i; // 绑定动态对象 u_i.reset(new int(3)); // 创建时绑定对象 std::unique_ptr<int> u_i2(new int(4)); // 指向类型为T的指针,用类型为D的对象d来代替默认的删除器 std::unique_ptr<T, D> u(d) // 释放所有权 int *p_i = u_i2.release(); // 转移所有权 std::unique_ptr<string> u_s(new string("abc")); std::unique_ptr<string> u_s2 = std::move(u_s); // 转移所有权 u_s2.reset(u_s.release()); // 显示销毁对象,相当于rest() u_s2 = nullptr;
需要注意的是,如果
std::unique_ptr通过移动语义转移了所有权之后,原先的对象也不能再直接访问了,因为已经置空了。保险起见,此时应该加入判断空的条件防止出错。std::unique_ptr<string> u0(new string("abc")); std::unique_ptr<string> u1 = std::move(u0); if (u0.get() != nullptr) { // do something }
std::uniqute_ptr<T>禁止了拷贝语义(试图拷贝时编译会报错),但如果是临时右值的话,编译器允许拷贝语义。std::unique_ptr<string> demo(const char *s) { std::unique_ptr<string> temp(new string(s)); return temp; // A temporary value, which is an rvalue } std::unique_ptr<string> ps; ps = demo("Unique Special Case") // allow copy sematics
std::uniqute_ptr<T>可以管理动态数组,因为它有std::uniqute_ptr<T[]>的重载版本,销毁动态对象时使用delete T[]std::uniqute_ptr<int []> p(new int[3]{0, 1, 2}); p[0] = 0; // overloaded: operator[]
std::uniqute_ptr<T, D>可以自定义删除操作(deleter)// clean up function void final_clean(Resource *p) { release_resource(p); } // 传入函数名,自动转换为函数指针 std::uniqute_ptr<Resource, decltype(final_clean)*> p(&c, final_clean);
std::auto_ptr<T>
std::auto_ptr现已摒弃不再使用std::auto_ptr没有禁止拷贝语义,赋值给新的std::auto_ptr之后,原先对象会失效,如果此时再去访问原先的对象,就会在运行时产生错误,造成程序崩溃。(std::unique_ptr就是禁止了拷贝语义来改善这种情况)std::auto_ptr不能放在容器中
std::weak_ptr<T>
基本特性
主要用来配合
shared_ptr使用,可以解决循环引用的问题weak_ptr可以像旁观者一样观察资源的使用情况,查看shared_ptr所引用的资源计数,但它weak_ptr本身不变引用计数weak_ptr必要时可以通过lock()生成一个对应的shared_ptr来获得资源的管理权(计数+1)weak_ptr可以被另一个weak_ptr或shared_ptr赋值(=)
基本用法
// 创建空的weak_ptr,指向类型为T的对象
std::weak_ptr<T> w;
// 与shared_ptr指向相同的对象,但shared_ptr的计数不变
// T必须是可以转换成sp所指向的类型
std::weak_ptr<T> w(sp);
// w是weak_ptr,p可以是weak_ptr或shared_ptr
// 赋值后w和p共享对象,但p这个shared_ptr的计数不增加
w = p;
// 置空
w.reset();
// 返回和w共享的对象的shared_ptr的数量
w.use_count();
// 如果w.use_count()为0,返回true,否则返回false
w.expired();
// 如果w.expired()返回true,则返回一个空的shared_ptr
// 否则返回非空的shared_ptr
w.lock();