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);
|
|||
|
```
|