auto_ptrc++ |
用于解决资源自动释放问题,见以下代码: if (error occur) |
unique_ptr函数 |
unique_ptr做为auto_ptr替代品。它对引用对象全部权专注,所以得名unique unique_ptr<Obj> ap(new Obj() ); unique_ptr<Obj> two = one; //errorc++11 也就是unique_ptr对对象的引用专注,不容许随意转移。对象 2) 可进行移动构造和移动赋值操做 |
shared_ptr内存 |
auto_ptr和unique_ptr只能用一个智能指针引用对象,而shared_ptr则是能够多个智能指针同时拥有一个对象。shared_ptr实现方式是采用引用计数。引用计数原理即多个智能指针同时引用一个对象,每当引用一次,引用计数加1,当一个智能指针销毁,引用计数减1,当引用计数减小到0的时释放引用对象。这种引用计数增减发生在智能指针的构造函数,复制构造函数,赋值操做符,析构函数中。这种方式使得多个智能指针同时对所引用的对象有拥有权,同时在引用计数减到0以后自动释放资源,也实现了auto_ptr和unique_ptr的资源释放功能。 } |
weak_ptr |
shared_ptr是一种强引用的关系,智能指针直接引用对象。那么这个代码有一个隐含的问题,就是循环引用,从而形成内存泄漏。示例看一个循环引用的例子。 |
应用总结 |
尽可能使用unique_ptr而不是auto_ptr shared_ptr知足大部分需求; weak_ptr避免递归的依赖关系; |
make_shared | 1. 在初始化unique_ptr或者shared_ptr时,优先使用std::make_unique和std::make_shared。缘由: 1)异常安全性 假设有以下函数声明: intcomputePriority(); processInvestment(std::shared_ptr<Investment>(newInvestment()),computePriority()); 因为在C++中函数参数的执行顺序不固定,因此在上面对函数processInvestment调用中,函数参数的执行顺序极可能是: new Investment computePriority() std::shared_ptr constructor 这种执行顺序的风险是,若是在第二步,执行computePriority的过程当中出现异常,那么在第一步中new出来的对象将变得不可访问,从而形成内存泄漏。 2)执行效率(对于shared_ptr而言) std::shared_ptr<Investment>ptr(new Investment); //方式1,new的方式在方式1中,会涉及到两次动态内存分配: 第1次是new Investment时,为Investment对象分配空间; 第2次是为控制块(Control Block)分配空间。 auto pIn = std::make_shared<Investment>();//方式2,make_shared的方式 在方式二中,一次动态内存分配就足够了,这是因为make_shared会为Investment对象和控制块(Control block)一次性分配一大块内存。因为只有一次内存分配,于是方式二提升了程序的执行效率。 二、make_xxx函数的弊端 既然使用make_xxx有这么多好处,是否应到处使用make函数而彻底放弃new方式?固然不是,make函数存在如下限制: 1) make函数不支持用户自定义释放器。因为make函数有本身的内存分配和析构规则,因此不适用于自定义分配器和释放器的对象。 2) make函数不支持大括号初始化方式。对于下面这句代码: auto spv = std::make_shared<vector<int>>(10,20); 意为spv指向一个vector,该vector有10个元素,每一个元素值为20。若是想实现的是这个vector有两个元素,分别为10,20的话,只能用new方式。 3) 内存释放不够灵活。 在使用new的方式中,有两块独立的堆内存,一块存放资源对象,一块存放控制块,当资源对象的引用计数为0的时候,资源对象会被销毁,它所占用的内存也会被随之销毁。 在使用make函数的方式中,make函数一次性为资源对象和控制块分配了一块内存,当资源对象的引用计数为0是,对象被销毁,可是资源对象占用的内存却不会被销毁,只有当控制块占用的内存被销毁是才会将资源对象所占内存一并释放。那么,控制块内存何时被释放呢?这就涉及到控制块中另外一个引用计数了,这个引用计数被称为“Weak Count”,其做用是用来计数指向该资源的weak_ptr的数量。当这个weak count的值为0时,控制块才会被释放。当资源对象很是庞大时,使用make函数的方式将形成不小的资源浪费。 |