整理一下c++中shared_ptr,weak_ptr,unique_ptr三种指针的使用案例和注意事项,让程序资源更加案例,在标准库中,需要包含<memory>,在boost库中,

  一. 智能指针unique_ptr

    与shared_ptr相似,区别在于unique_ptr是独立拥有对象权,因此只有move语言,无拷贝语义,不做其它详述了。

  二.智能指针share_ptr

  1.基本使用

class Sam
{
public:
Sam(int v):val(v) { }
int32_t val;

    ~Sam()
    {
      std::cout << "~sam()" << std::endl;
    }

};

//define
std::shared_ptr<Sam> p1(new Sam());
std::shared_ptr<Sam> p2 = std::make_shared<Sam>();
p1.reset(new Sam(300));  //new first, delete second
std::shared_ptr<Sam> p3 = p1; //get the base ptr
Sam* pSam = p1.get(); //modify
(*p1).val = 10000; //cal is 1
bool b = p1.unique(); p1.reset();

  2.高级使用

  (1)使用shared_ptr<list<T>>类型,调用reset的时候list中的所有的Sam对象都会调用析构函数

std::shared_ptr<std::list<Sam>> lst_ptr( new std::list<Sam>(, ));
std::cout << lst_ptr.get()->size() << std::endl;
lst_ptr.reset();

  (2)程序不知道自己需要使用多少对象. 且程序需要在多个对象间共享数据,使用vector<shared_ptr<T>>类型:

std::vector<std::shared_ptr<Sam>> vec_ptr;
std::shared_ptr<Sam> p1(new Sam());
vec_ptr.push_back(p1);

  (3)定制自己的删除器:在shared_ptr释放时会自动调用 函数删除器而不是默认的析构函数了:

void Deleter(Sam* obj) {
std::cout << "Deleter" << std::endl;
} std::shared_ptr<Sam> sp(new Sam(10), Deleter);

  如果将删除器定义成类,则自由性更大,下面的代码执行后会调用析构函数(简单地使用了delete)

template<typename T>
class Deleter
{
public:
void operator () (T* x) const
{
if (x != NULL)
{
std::cout << __LINE__ << std::endl;
delete x;
x = NULL;
}
}
}; std::shared_ptr<Sam> sp(new Sam(10), Deleter<Sam> {})

  3.错误用法

  情形一:一个指针同时放入两个shared_ptr,会在第二个shared_ptr释放时引发异常。

pSam = new Sam();
std::shared_ptr<Sam> p4(pSam);
std::shared_ptr<Sam> p5(pSam);

  情形二:数据结构形成环的时候,shared_ptr不能正常工作,需要与weak_ptr协作解决此问题,用例如下:

class CB;
class CA; class CA
{
public:
CA() {}
~CA() { std::cout << "~CA()" << std::endl; } void Register(const std::shared_ptr<CB>& sp)
{
m_sp = sp;
} private:
std::shared_ptr<CB> m_sp;
}; class CB
{
public:
CB() {};
~CB() { std::cout << "~CB()" << std::endl; }; void Register(const std::shared_ptr<CA>& sp)
{
m_sp = sp;
} private:
std::shared_ptr<CA> m_sp;
};   std::shared_ptr<CA> spa(new CA);
std::shared_ptr<CB> spb(new CB); spb->Register(spa);
spa->Register(spb); printf("%d\n", spb.use_count()); //
printf("%d\n", spa.use_count()); //

  程序结束后,无法释放内存,也没有调用析构函数,智能指针的引用计数都是2,这就是循环引用问题。

  情形三:普通类继承 enable_shared_from_this 的错误情况:

  

class Y : public std::enable_shared_from_this<Y>
{
public:
std::shared_ptr<Y> GetSharePtr()
{
return shared_from_this();
}
};

    Y y;
    std::shared_ptr<Y> spy = y.GetSharePtr(); // 错误, y 根本不是 new 创建的
    Y* y = new Y;
    std::shared_ptr<Y> spy = y->GetSharePtr(); // 错误, 问题依旧存在, 程序直接崩溃

    std::shared_ptr<Y> spy(new Y);
    std::shared_ptr<Y> p = spy->GetSharePtr();
    printf("%d\n", p.use_count()); // 2

  前两者错误是因为虽然Y由 enable_shared_from_this派生,但智能指针的数据结构并没有因为new Y的操作赋值 。

  

  三. 智能指针weak_ptr

  构造和析构不会引起引用计数的增加或减少。没有重载 * 和 -> 但可以使用lock获得一个可用的shared_ptr对象,且在所指对象内存已经无效时,返回指针空值nullptr.

  带有的成员函数reset,use_count

std::shared_ptr<Sam> sam_ptr(new Sam());
std::weak_ptr<Sam> sam_wk = sam_ptr; std::shared_ptr<Sam> sp = sam_wk.lock();
if (sp)
{
std::cout << (*sp).val << endl;  // 6
}
std::cout << sp.use_count() << std::endl;  //2

  

C++ 标准库智能指针的更多相关文章

  1. c/c++ 标准库 智能指针( smart pointer ) 是啥玩意儿

    标准库 智能指针( smart pointer ) 是啥玩意儿 一,为什么有智能指针??? c++程序员需要自己善后自己动态开辟的内存,一旦忘了释放,内存就泄露. 智能指针可以帮助程序员"自 ...

  2. 详解 boost 库智能指针(scoped_ptr<T> 、shared_ptr<T> 、weak_ptr<T> 源码分析)

    一.boost 智能指针 智能指针是利用RAII(Resource Acquisition Is Initialization:资源获取即初始化)来管理资源.关于RAII的讨论可以参考前面的文章.在使 ...

  3. C++11标准的智能指针、野指针、内存泄露的理解(日后还会补充,先浅谈自己的理解)

    1.野指针的概念.成因以及避免 首先,来说说什么是野指针,所谓野指针就是一个指向未申请访问受限的内存区域或者已经删除了的对象的指针. 什么意思呢?就是本来一个指针指向一个对象.一块内存,但是由于程序( ...

  4. c++ 智能指针(转)

    智能指针的使用 智能指针是在 <memory> 标头文件中的 std 命名空间中定义的. 它们对 RAII 或“获取资源即初始化”编程惯用法至关重要. 此习惯用法的主要目的是确保资源获取与 ...

  5. 现代C++学习笔记之一入门篇:智能指针(C++ 11)

    原始指针:通过new建立的*指针 智能指针:通过智能指针关键字(unique_ptr, shared_ptr ,weak_ptr)建立的指针 在现代 C++ 编程中,标准库包含智能指针,该指针用于确保 ...

  6. 智能指针auto_ptr & shared_ptr

    转载:智能指针auto_ptr 很多人听说过标准auto_ptr智能指针机制,但并不是每个人都天天使用它.这真是个遗憾,因为auto_ptr优雅地解决了C++设计和编码中常见的问题,正确地使用它可以生 ...

  7. C++ auto_ptr智能指针的用法

    C++中指针申请和释放内存通常采用的方式是new和delete.然而标准C++中还有一个强大的模版类就是auto_ptr,它可以在你不用的时候自动帮你释放内存.下面简单说一下用法. 用法一: std: ...

  8. C++ Pirmer : 第十四章 : 重载运算符与类型转换之函数调用运算符与标准库的定义的函数对象

    函数调用运算符 struct test { int operator()(int val) const { return (i > 0 ? i : -i); } }; 所谓的函数调用就是一个类重 ...

  9. 标准库中的智能指针shared_ptr

    智能指针的出现是为了能够更加方便的解决动态内存的管理问题.注:曾经记得有本书上说可以通过vector来实现动态分配的内存的自动管理,但是经过试验,在gcc4.8.5下是不行的.这个是容易理解的,vec ...

随机推荐

  1. Resque基本

    原文:http://www.cnblogs.com/rywx/archive/2012/05/26/2519615.html Resque resque是基于redis的后台任务组件,能把任何类或模块 ...

  2. 第一章 深入Web请求过程(待续)

    B/S网络架构概述 如何发起一个请求 HTTP解析 DNS域名解析 CDN工作机制

  3. java.lang.OutOfMemoryError: Java heap space异常

    最近使用Tomcat跑项目时,其他项目可以正常运行,但有一个项目报java.lang.OutOfMemoryError: Java heap space异常,查了资料后,找到一个处理我所遇见异常的解决 ...

  4. intellij idea打包springboot项目

    一.可执行jar包 注意点: maven的package类型需要为jar 配置了spring-boot-mavne-plugin插件 1.1.pom.xml <?xml version=&quo ...

  5. TextView 点击拨打电话

    点击TextView,拨打电话 TextView属性:android:autoLink="phone" 需要配置文件中的属性 <uses-permission android ...

  6. adb device offline 解决办法

    当电脑中的豌豆荚之类的应用打开的状态下 adb devices 显示连接状态 关闭手机助手之后,adb devices总显示 device offline 后来发现sdk  platform-tool ...

  7. ie6下会拒绝高度小于字号的设置

    <div style="height: 5px;background-color: yellow">wojitianhenkaixin</div> 此时浏览 ...

  8. C++ 结构体的构造函数和析构函数

    在C++中除了类中可以有构造函数和析构函数外,结构体中也可以包含构造函数和析构函数,这是因为结构体和类基本雷同,唯一区别是,类中成员变量默认为私有,而结构体中则为公有.注意,C++中的结构体是可以有析 ...

  9. Java-马士兵设计模式学习笔记-工厂模式-抽象工厂模式

    一.概述 1.抽象工厂:当情况是需要产生一系列产品,若需更换产品,则要求一系列产品一起换,且要控制一系列产品的产生过程,此时可考虑抽象工厂模式.例:小明装修屋子,把电视.冰箱都替换掉,他这次需要把电视 ...

  10. 51NOD 1616 最小集合

    传送门 分析 不难发现集合中的数一定是集合内其它一堆数的$gcd$ 于是我们枚举$i$,统计原来集合中有几个数是$i$的倍数,设这个值为$f(i)$ 之后对于每个$i$如果不存在$f(x*i) = f ...