141 lines
		
	
	
		
			3.4 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
		
		
			
		
	
	
			141 lines
		
	
	
		
			3.4 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
| 
								 | 
							
								## 使用c++11解决内存泄露的问题
							 | 
						|||
| 
								 | 
							
								### 4.1 shared_ptr共享的智能指针
							 | 
						|||
| 
								 | 
							
								1. 初始化<br>
							 | 
						|||
| 
								 | 
							
								优先通过make_shared来构造智能指针
							 | 
						|||
| 
								 | 
							
								```
							 | 
						|||
| 
								 | 
							
								std::shared_ptr<int> p(new int(1));
							 | 
						|||
| 
								 | 
							
								std::shared_ptr<int> p2=p;
							 | 
						|||
| 
								 | 
							
								std::shared_ptr<int> ptr;
							 | 
						|||
| 
								 | 
							
								ptr.reset(new int(1));
							 | 
						|||
| 
								 | 
							
								```
							 | 
						|||
| 
								 | 
							
								2. 获取原始指针<br>
							 | 
						|||
| 
								 | 
							
								```
							 | 
						|||
| 
								 | 
							
								std::shared_ptr<int> ptr(new int(1));
							 | 
						|||
| 
								 | 
							
								int *p=ptr.get();
							 | 
						|||
| 
								 | 
							
								```
							 | 
						|||
| 
								 | 
							
								3. 指定删除器
							 | 
						|||
| 
								 | 
							
								```
							 | 
						|||
| 
								 | 
							
								void DeleteIntPtr(int *p){
							 | 
						|||
| 
								 | 
							
								    delete p;
							 | 
						|||
| 
								 | 
							
								}
							 | 
						|||
| 
								 | 
							
								std::shared_ptr<int> p(new int,DeleteIntPtr);
							 | 
						|||
| 
								 | 
							
								//当然也可以用lambda
							 | 
						|||
| 
								 | 
							
								std::shared_ptr<int> p(new int,[](int* p){delete p;});
							 | 
						|||
| 
								 | 
							
								```
							 | 
						|||
| 
								 | 
							
								#### 4.2.1 使用shared_ptr需要注意的问题
							 | 
						|||
| 
								 | 
							
								1. 不要用一个原始指针初始化多个shared_ptr
							 | 
						|||
| 
								 | 
							
								```
							 | 
						|||
| 
								 | 
							
								int* ptr=new int;
							 | 
						|||
| 
								 | 
							
								std::shared_ptr<int> p1(ptr);
							 | 
						|||
| 
								 | 
							
								std::shared_ptr<int> p2(ptr);
							 | 
						|||
| 
								 | 
							
								```
							 | 
						|||
| 
								 | 
							
								2. 不要在函数实参中创建shared_ptr
							 | 
						|||
| 
								 | 
							
								```
							 | 
						|||
| 
								 | 
							
								function(shared_ptr<int>(new int),g())  //有缺陷,不同编译器的执行顺序不一样
							 | 
						|||
| 
								 | 
							
								shared_ptr<int> p(new int());
							 | 
						|||
| 
								 | 
							
								f(p,g());
							 | 
						|||
| 
								 | 
							
								```
							 | 
						|||
| 
								 | 
							
								3. 通过shared_from_this()返回的this指针,不要将指针作为shared_ptr返回出来,因为this本子上是个裸指针。
							 | 
						|||
| 
								 | 
							
								4. 避免循环引用
							 | 
						|||
| 
								 | 
							
								```
							 | 
						|||
| 
								 | 
							
								struct A;
							 | 
						|||
| 
								 | 
							
								struct B;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								struct A{
							 | 
						|||
| 
								 | 
							
								  std::shared_ptr<B> bptr;  
							 | 
						|||
| 
								 | 
							
								};
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								struct B{
							 | 
						|||
| 
								 | 
							
								  std::shared_ptr<A> bptr;  
							 | 
						|||
| 
								 | 
							
								};
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								void TestPtr(){
							 | 
						|||
| 
								 | 
							
								    {
							 | 
						|||
| 
								 | 
							
								        std::shared_ptr<A> ap(new A);  
							 | 
						|||
| 
								 | 
							
								        std::shared_ptr<B> bp(new B);
							 | 
						|||
| 
								 | 
							
								        ap->bptr=bp;
							 | 
						|||
| 
								 | 
							
								        bp->aptr=ap;
							 | 
						|||
| 
								 | 
							
								        //计数不会归零,无法正确销毁
							 | 
						|||
| 
								 | 
							
								    }
							 | 
						|||
| 
								 | 
							
								}
							 | 
						|||
| 
								 | 
							
								```
							 | 
						|||
| 
								 | 
							
								### 4.2 unique_ptr独占的智能指针
							 | 
						|||
| 
								 | 
							
								它不允许其他的智能指针共享内部的指针,不允许通过复制将unique_ptr赋值给另一个unique_ptr<br>
							 | 
						|||
| 
								 | 
							
								但是可以通过std::move将拥有权转移
							 | 
						|||
| 
								 | 
							
								```
							 | 
						|||
| 
								 | 
							
								std::shared_ptr<T> myPtr(new T);  
							 | 
						|||
| 
								 | 
							
								std::shared_ptr<T> myOtherPtr=std::move(myPtr);  
							 | 
						|||
| 
								 | 
							
								```
							 | 
						|||
| 
								 | 
							
								### 4.3 weak_ptr弱引用的智能指针
							 | 
						|||
| 
								 | 
							
								弱引用指针weak_ptr是用来监视shared_ptr的生命周期的,不会使引用计数加1.同时他可以解决返回this指针和解决循环引用的问题。
							 | 
						|||
| 
								 | 
							
								#### 4.3.1 weak_ptr基本用法
							 | 
						|||
| 
								 | 
							
								1. 通过use_count()方法来获得当前观测资源的引用计数
							 | 
						|||
| 
								 | 
							
								```
							 | 
						|||
| 
								 | 
							
								std::shared_ptr<int> sp(new int(10));
							 | 
						|||
| 
								 | 
							
								std::weak_ptr<int> wp(sp);
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								std::cout<<wp.use_count()<<std::endl;
							 | 
						|||
| 
								 | 
							
								```
							 | 
						|||
| 
								 | 
							
								2. 通过expired()来判断资源是否释放
							 | 
						|||
| 
								 | 
							
								```
							 | 
						|||
| 
								 | 
							
								std::shared_ptr<int> sp(new int(10));
							 | 
						|||
| 
								 | 
							
								std::weak_ptr<int> wp(sp);
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								if(wp.expired())
							 | 
						|||
| 
								 | 
							
								{
							 | 
						|||
| 
								 | 
							
								    std::cout<<"weak_ptr无效,资源释放”<<std::endl;
							 | 
						|||
| 
								 | 
							
								}else{
							 | 
						|||
| 
								 | 
							
								    std::cout<<"weak_ptr有效"<<std::endl;
							 | 
						|||
| 
								 | 
							
								}
							 | 
						|||
| 
								 | 
							
								```
							 | 
						|||
| 
								 | 
							
								3. 通过lock方法获取所监视的shared_ptr
							 | 
						|||
| 
								 | 
							
								#### 4.3.2 weak_ptr返回this指针
							 | 
						|||
| 
								 | 
							
								通过派生std::enable_shared_from_this类,并通过shader_from_this来返回智能指针
							 | 
						|||
| 
								 | 
							
								#### 4.3.3 weak_ptr解决循环引用问题
							 | 
						|||
| 
								 | 
							
								```
							 | 
						|||
| 
								 | 
							
								struct A;
							 | 
						|||
| 
								 | 
							
								struct B;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								struct A{
							 | 
						|||
| 
								 | 
							
								  std::shared_ptr<B> bptr;  
							 | 
						|||
| 
								 | 
							
								};
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								struct B{
							 | 
						|||
| 
								 | 
							
								  std::weak_ptr<A> bptr;  
							 | 
						|||
| 
								 | 
							
								  //改成weak_ptr就能正常销毁了
							 | 
						|||
| 
								 | 
							
								};
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								void TestPtr(){
							 | 
						|||
| 
								 | 
							
								    {
							 | 
						|||
| 
								 | 
							
								        std::shared_ptr<A> ap(new A);  
							 | 
						|||
| 
								 | 
							
								        std::shared_ptr<B> bp(new B);
							 | 
						|||
| 
								 | 
							
								        ap->bptr=bp;
							 | 
						|||
| 
								 | 
							
								        bp->aptr=ap;
							 | 
						|||
| 
								 | 
							
								    }
							 | 
						|||
| 
								 | 
							
								}
							 | 
						|||
| 
								 | 
							
								```
							 | 
						|||
| 
								 | 
							
								### 4.4通过智能指针管理第三方库分配的内存
							 | 
						|||
| 
								 | 
							
								```
							 | 
						|||
| 
								 | 
							
								void* p=GetHandle()->Create();
							 | 
						|||
| 
								 | 
							
								std::shared_ptr<void> sp(p,[this](void*p){GetHandle()->Release(p);});
							 | 
						|||
| 
								 | 
							
								```
							 | 
						|||
| 
								 | 
							
								包装公共函数
							 | 
						|||
| 
								 | 
							
								```
							 | 
						|||
| 
								 | 
							
								std::shared_ptr<void> Guard(void* p)
							 | 
						|||
| 
								 | 
							
								{
							 | 
						|||
| 
								 | 
							
								    return std::shared_ptr<void> sp(p,[this](void *p){GetHandle()->Release(p);});
							 | 
						|||
| 
								 | 
							
								}
							 | 
						|||
| 
								 | 
							
								```
							 | 
						|||
| 
								 | 
							
								但是不够安全
							 | 
						|||
| 
								 | 
							
								```
							 | 
						|||
| 
								 | 
							
								void *p=GetHandle()->Create();
							 | 
						|||
| 
								 | 
							
								Guard(p);
							 | 
						|||
| 
								 | 
							
								//Guard(p);是个右值,如果没有被赋予给auto指针,这句结束就会释放从而导致p提前释放
							 | 
						|||
| 
								 | 
							
								```
							 | 
						|||
| 
								 | 
							
								可以使用宏来解决
							 | 
						|||
| 
								 | 
							
								```
							 | 
						|||
| 
								 | 
							
								#define GUARD(p) std::shared_ptr<void> p##p(p,
							 | 
						|||
| 
								 | 
							
								void *p=GetHandle()->Create();
							 | 
						|||
| 
								 | 
							
								Guard(p);
							 | 
						|||
| 
								 | 
							
								```
							 |