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