这章主要学习智能指针。
- shared_ptr
1.初始化方式
优先采用make_shared的方式来初始化,因为其更高效。
int *p = new int();
std::shared_ptr<int> bptr(p);//方式1
std::shared_ptr<int> aptr = std::make_shared<int>(2);//方式 2
std::shared_ptr<int> cptr(aptr); //方式3
//std::shared_ptr<int>p = new int(10);//error,不能这样赋值
2.获取原始指针
std::shared_ptr<int> p1(new int(10));
int *ptr = p1.get();//通过get()返回原始指针
3.删除器
//删除器,针对shared_ptr管理动态数组的时候
//采用lambda表达式创建个删除int数组的删除器 [](int *p) {delete[]p; }
std::shared_ptr<int> pArr(new int[10], [](int *p) {delete[]p; });
4‘注意事项
//error 不能用一个原始指针初始化多个shared_ptr,程序会崩溃
int *p1 = new int(1);
std::shared_ptr<int> pp(p1);
std::shared_ptr<int> pp1(p1);
//ok shared_ptr允许多个指针指向同一个对象
std::shared_ptr<A> sp1(new A());
std::shared_ptr<A> sp2 = sp1;
class A
{
public:
std::shared_ptr<A> GetSelf()
{
return std::shared_ptr<A>(this);
}
~A()
{
std::cout << "ss" << std::endl;
}
};
std::shared_ptr<A> sp2 = sp1->GetSelf(); //error 一个this指向两个对象sp1和sp2,return的this会导致重复析构
//用enable_shared_from_this来解决shared_ptr返回this指针的问题
class A :public std::enable_shared_from_this<A>
{
public:
std::shared_ptr<A> GetSelf()
{
return shared_from_this();
}
~A()
{
std::cout << "ss" << std::endl;
}
};
use_count()函数用来记录有多少个shared_ptr指向某个开辟的对象
- unique_ptr
//unique_ptr是独占性指针,不允许有多个指针对象指向一个地址空间
//使用move函数就可以了
std::unique_ptr<int> uptr(new int());
std::unique_ptr<int> uptr1 = uptr;//error
std::unique_ptr<int> uptr2 = std::move(uptr);//ok
unique_ptr和shared_ptr相比,其具有以下两个特点
//unique_ptr可以指向数组,而shared_ptr不可以
//std::unique_ptr<int[]> pArr(new int[10]);//ok
std::shared_ptr<int[]>pArr1(new int[10]);//error
//删除器不同
std::shared_ptr<int>pShare(new int[2], [](int *p) {delete[]p; });//ok
//std::unique_ptr<int>pUni(new int[2], [](int *p) {delete[] p; });//error
//unique_ptr删除器在使用时需确定删除器的类型
std::unique_ptr<int, std::function<void(int*)>>pUni(new int[2], [](int *p) {delete[] p; });//ok
- weak_ptr
1.weak_ptr不会是引用计数加1,不管理shared_ptr,其相当于shared_ptr的助手,用来监控shared_ptr
std::weak_ptr<int> g_w;
void func()
{
if (g_w.expired())
{
std::cout << "no shared_ptr" << std::endl;
}
else
{
auto sp = g_w.lock();
std::cout << "is " << *sp << std::endl;
}
}
std::shared_ptr<int>pp1(new int());
std::weak_ptr<int>pw(pp1);
std::cout << "pp1 = " << pp1.use_count() << std::endl;//等于1
//expired来监控资源是否释放
//lock来获取所监控的shared_ptr
{
std::shared_ptr<int> pp2 = std::make_shared<int>(9);
g_w = pp2;
func();
}
func();
//输出结果为:
//is 9
//no shared_ptr
2.weak_ptr用来解决循环引用
class B;
class C;
class B
{
public:
std::shared_ptr<C> cptr;
~B()
{
std::cout << "B is deleted" << std::endl;
}
};
class C
{
public:
std::weak_ptr<B> bptr;//ok,会走到两个析构函数中,打印输出
//std::shared_ptr<B> bptr;//error,不会走到两个析构函数
~C()
{
std::cout << "C is deleted" << std::endl;
}
};
main.cpp
std::shared_ptr<B> bp(new B);
std::shared_ptr<C> cp(new C);
bp->cptr = cp;
cp->bptr = bp;
std::cout << bp.use_count() << std::endl;//都采用shared_ptr时输出2,离开作用域之后变为1,其还是无法删除指针,导致内存泄露
因为weak_ptr本身不会使引用计数加1,即此时bptr仍是1,离开作用于之后,其值减1变为0,B被析构。B析构后其内部的cptr计数减1,离开作用域后cptr技术再减1变为0,C也被析构。
完整调试程序
#include <iostream>
#include <memory>
#include <functional>
std::weak_ptr<int> g_w;
void func()
{
if (g_w.expired())
{
std::cout << "no shared_ptr" << std::endl;
}
else
{
auto sp = g_w.lock();
std::cout << "is " << *sp << std::endl;
}
}
//class A
//{
//public:
// std::shared_ptr<A> GetSelf()
// {
// return std::shared_ptr<A>(this);
// }
// ~A()
// {
// std::cout << "ss" << std::endl;
// }
//};
//用enable_shared_from_this来解决shared_ptr返回this指针的问题
class A :public std::enable_shared_from_this<A>
{
public:
std::shared_ptr<A> GetSelf()
{
return shared_from_this();
}
~A()
{
std::cout << "ss" << std::endl;
}
};
class B;
class C;
class B
{
public:
std::shared_ptr<C> cptr;
~B()
{
std::cout << "B is deleted" << std::endl;
}
};
class C
{
public:
std::weak_ptr<B> bptr;
//std::shared_ptr<B> bptr;
~C()
{
std::cout << "C is deleted" << std::endl;
}
};
int main()
{
//std::shared_ptr<int>p = new int(10);//error,不能这样赋值
//std::shared_ptr<int> p1(new int(10));
//int *ptr = p1.get();//通过get()返回原始指针
int *p = new int();
std::shared_ptr<int> bptr(p);//方式1
std::shared_ptr<int> aptr = std::make_shared<int>(2);//方式 2
std::shared_ptr<int> cptr(aptr); //方式3
//删除器,针对shared_ptr管理动态数组的时候
//采用lambda表达式创建个删除int数组的删除器 [](int *p) {delete[]p; }
std::shared_ptr<int> pArr(new int[10], [](int *p) {delete[]p; });
//error 不能用一个原始指针初始化多个shared_ptr,程序会崩溃
//int *p1 = new int(1);
//std::shared_ptr<int> pp(p1);
//std::shared_ptr<int> pp1(p1);
//shared_ptr允许多个指针指向同一个对象
std::shared_ptr<A> sp1(new A());
std::shared_ptr<A> sp2 = sp1;
std::shared_ptr<A> sp3 = sp1->GetSelf(); //error 一个this指向两个对象sp1和sp2,return的this会导致重复析构
//use_count()函数用来记录有多少个shared_ptr指向某个开辟的对象
//{
std::shared_ptr<B> bp(new B);
std::shared_ptr<C> cp(new C);
bp->cptr = cp;
cp->bptr = bp;
std::cout << bp.use_count() << std::endl;//都采用shared_ptr时输出2
//}
//unique_ptr是独占性指针,不允许有多个指针对象指向一个地址空间
//std::unique_ptr<int> uptr(new int());
//std::unique_ptr<int> uptr1 = uptr;//error
//unique_ptr可以指向数组,而shared_ptr不可以
//std::unique_ptr<int[]> pArr(new int[10]);//ok
//std::shared_ptr<int[]>pArr1(new int[10]);//error
//删除器不同
std::shared_ptr<int>pShare(new int[2], [](int *p) {delete[]p; });//ok
//std::unique_ptr<int>pUni(new int[2], [](int *p) {delete[] p; });//error
//unique_ptr删除器在使用时需确定删除器的类型
std::unique_ptr<int, std::function<void(int*)>>pUni(new int[2], [](int *p) {delete[] p; });//ok
//weak_ptr不会是引用计数加1,不管理shared_ptr,其相当于shared_ptr的助手,用来监控shared_ptr
std::shared_ptr<int>pp1(new int());
std::weak_ptr<int>pw(pp1);
std::cout << "pp1 = " << pp1.use_count() << std::endl;//等于1
//expired来监控资源是否释放
//lock来获取所监控的shared_ptr
{
std::shared_ptr<int> pp2 = std::make_shared<int>(9);
g_w = pp2;
func();
}
func();
return 0;
}