当前位置: 代码迷 >> 综合 >> C++11学习(3)
  详细解决方案

C++11学习(3)

热度:77   发布时间:2024-02-20 12:12:26.0

这章主要学习智能指针。

  • 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);//方式 2std::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;//errorstd::unique_ptr<int> uptr2 = std::move(uptr);//ok

unique_ptr和shared_ptr相比,其具有以下两个特点

	//unique_ptr可以指向数组,而shared_ptr不可以//std::unique_ptr<int[]> pArr(new int[10]);//okstd::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.cppstd::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也被析构。

  相关解决方案