shared_ptr | unique_ptr | |
---|---|---|
特点 | 使用引用计数。每个指针的拷贝都指向同一片资源 | 独占性 不支持复制但可以转移 |
关于数组 | 在C+17之前, shared_ptr能不用于管理动态分配的数组。要管理就必须自己写删除器。 | 可以指向数组 |
删除器 | 制定时,需要确认删除器的类型 |
本章笔记参考书《深入应用C++11》
学完以后发现书里的内容太浅了,附上我师傅 逗逼老师 的文章共参考
https://blog.csdn.net/fl2011sx/article/details/103941346
shared_ptr
分析时当模板类分析,使用时当指针使用
基本用法
初始化
// study20200206.cpp : This file contains the 'main' function. Program execution begins and ends there.
//
#include <iostream>
#include <memory>
int main()
{
// 1.直接初始化
std::shared_ptr<int> p(new int(1));
std::shared_ptr<int> p2 = p;
std::cout << "p2.count = " << p2.use_count() << std::endl;
// 2.make_shared 更高效。调用构造函数
std::shared_ptr<int> pp = std::make_shared<int>(2);
std::cout << "pp.count = " << pp.use_count() << std::endl;
// 3.reset重新初始化
std::shared_ptr<int> ptr;
ptr.reset(new int(3));
std::cout << "*ptr = " << *ptr;
}
获取原始指针
std::shared_ptr<int> pp = std::make_shared<int>(2);
int *p = pp.get();
指定删除器
初始化时也可以指定删除器(删除时候调用的函数,可以是lambda)
1. 函数作为删除器
void DeleteIntPtr(int *p) {
delete p;
}
std::shared_ptr<int> pp(new int, DeleteIntPtr);
2. lambda
std::shared_ptr<int> pp(new int, [](int* p){ delet p; });
3. struct自定义删除器,重载()
template< typename T >
struct shared_deleter{
void operator ()( T const * p) {
delete p;
}
};
std::shared_ptr<int> sp(new int(3), shared_deleter<int>());
shared_ptr的默认删除器不支持数组对象,可以通过以下方法指定删除器
1.std::default_delete,内部通过调用delete
std::shared_ptr<int> pp(new int[3], std::default_delete<int[]>());
2. lambda
std::shared_ptr<int> pp(new int[3], [](int* p){ delet[] p; });
3.封装default_delete
template<typename T>
shared_ptr<T> make_shared_my(size_t size) {
return shared_ptr<T>(new T[size], std::default_delete<T[]>());
}
4. struct自定义删除器,重载()
template< typename T >
struct array_deleter{
void operator ()( T const * p) {
delete[] p;
}
};
std::shared_ptr<int> sp(new int[10], array_deleter<int>());
shared_from_this
this的智能指针叫shared_from_this()
std::enable_shared_from_this<T>
类中有一个weak_ptr在监视this智能指针,当调用shared_from_this方法时,会调用内部weak_ptr的lock()方法
class A : public std::enable_shared_from_this<A> {
std::shared_ptr<A> getSelf() {
return shared_from_this();
}
};
需要注意的
-
1) 不要使用原始指针直接初始化多个shared_ptr。
他们的内存计数不共享,达不到自动释放内存的目的。 -
2) 不要在函数实参中创建shared_ptr
函数参数计算顺序不同可能会内存泄露。 -
3) 避免循环引用。
A,B类中都有一个对方的智能指针。导致永远无法释放内存。
unique_ptr
不允许赋值,但可以通过std::move
转移资源
std::unique_ptr<int> up(new int(10));
std::unique_ptr<int> up2 = std::move(up);
// std::unique_ptr<int> up2 = up; error 不能用来复制
std::cout << "up2 = " << *up2 << std::endl;
删除器 语法和shared_ptr不同
指定时需要确认类型
std::unique_ptr<int, void(*)(int *)> ptr(new int(2), [](int *p) { delete *p;} );
如果需要使用捕获列表:(因为lambda表达式只有在捕获列表空时,才能转换为函数指针)
std::unique_ptr<int, std::function<void(int *)> ptr(new int(2), [&](int *p) { delete *p;} );
自己写删除器
struct array_deleter_int {
void operator ()(int const* p) {
std::cout << "array_deleter_int" << std::endl;
delete[] p;
}
array_deleter_int() {
std::cout << " array_deleter_int constructor" << std::endl;
}
};
std::unique_ptr<int, array_deleter_int> up3(new int(2));
weak_ptr
作为一个旁观者来监视shared_ptr中管理的资源是否存在。
基本用法
1. use_count()
std::shared_ptr<int> sp(new int[10]);
std::weak_ptr<int> wp(sp);
std::cout << "wp.use_count() = " << wp.use_count();
2.expired()判断资源是否被释放
true--被释放了,weak_ptr无效
3.lock()获取监视的shared_ptr