智能指针主要用于管理在堆上分配的内存,它将普通的指针封装为一个栈对象。当栈对象的生存周期结束后,会在析构函数中释放掉申请的内存,从而防止内存泄漏。ios
智能指针的做用是管理一个指针,由于存在如下这种状况:申请的空间在函数结束时忘记释放,形成内存泄漏。使用智能指针能够很大程度上的避免这个问题,由于智能指针就是一个类,当超出了类的做用域是,类会自动调用析构函数,析构函数会自动释放资源。因此智能指针的做用原理就是在函数结束时自动释放内存空间,不须要手动释放内存空间,有效避免内存泄漏的问题。 c++
智能指针定义于 memory (非memory.h)中, 命名空间为 std函数
unique_ptr,是用于取代c++98的auto_ptr的产物指针
unique_ptr 独占所指向的对象, 同一时刻只能有一个 unique_ptr 指向给定对象(经过禁止拷贝语义, 只有移动语义来实现), 定义于 memory (非memory.h)中, 命名空间为 std.调试
(C++98的方案,C++11已经抛弃)采用全部权模式。
auto_ptr 适合用来管理生命周期比较短或者不会被远距离传递的动态对象, 最好是局限于某个函数内部或者是某个类的内部.code
因为 auto_ptr 基于排他全部权模式:两个指针不能指向同一个资源,复制或赋值都会改变资源的全部权。对象
#include <iostream> #include <memory> class Test { public: void print() { std::cout << "Test::Print" << std::endl; } }; int main() { std::auto_ptr<Test> pTest1(new Test); pTest1->print(); std::auto_ptr<Test> pTest2(pTest1); //复制构造函数 pTest2->print(); std::cout << "pTest1 pointer:" << pTest1.get() << std::endl; //auto_ptr类的成员函数get()返回一个原始的指针 std::cout << "pTest2 pointer:" << pTest2.get() << std::endl; return 0; } //打印结果: Test::Print Test::Print pTest1 pointer:00000000 pTest2 pointer:01659548 //通过复制构造以后,pTest1所指向资源的全部权转向了pTest2,而pTest1变成空,两者不能同时共享该资源。
auto_ptr 主要有两大问题:生命周期
基于引用计数模型。资源能够被多个指针共享,它使用计数机制来代表资源被几个指针共享。内存
每次有 shared_ptr 对象指向资源,引用计数器就加1;当有 shared_ptr 对象析构时,计数器减1;当计数器值为0时,被指向的资源将会被释放掉。且该类型的指针可复制和可赋值,即其可用于STL容器中。此外,shared_ptr 指针可与多态类型和不彻底类型一块儿使用。资源
std::shared_ptr 智能指针共享所指向的资源(全部权),即几个 shared_ptr 可同时拥有一个对象,且共享一个控制块(constrol block),包含指向资源的 shared_ptr对象个数、指向资源的 weak_ptr 对象个数以及删除器(deleter:用户自定义的用于释放资源的函数,能够默认没有)。
一个空的 shared_ptr 对象不拥有任何资源和控制块。另外一方面,一个 shared_ptr 初始化为一个NULL 指针和一个控制块,这有别有空的 shared_ptr。当共享的引用计数器为0时,资源释放(delete 操做符释放,或由用户提供的 删除器 释放它)。
#include <iostream> #include <memory> class Test { public: void print() { std::cout << "Test::Print" << std::endl; } }; int main() { std::shared_ptr<Test> pTest1(new Test); pTest1->print(); std::shared_ptr<Test> pTest2(pTest1); //复制构造函数 pTest2->print(); std::cout << "pTest1 pointer:" << pTest1.get() << std::endl; //shared_ptr类的成员函数get()返回一个原始的指针 std::cout << "pTest2 pointer:" << pTest2.get() << std::endl; std::cout << "count pTest1:" << pTest1.use_count() << std::endl; //shared_ptr类的成员函数use_count():返回多少个智能指针指向某个对象,主要用于调试。 std::cout << "count pTest2:" << pTest2.use_count() << std::endl; return 0; } //打印结果: Test::Print Test::Print pTest1 pointer:00C29550 pTest2 pointer:00C29550 count pTest1:2 count pTest2:2 //pTest2建立后,pTest1对资源的全部权并无被剥夺,而是pTest1 和 pTest2 均指向了资源,且此时资源的引用计数为2。当两个shard\_ptr 指针pTest一、pTest2 超过其做用域时,最后一个析构的指针将会导致资源的释放(由于引用计数为0了)。
待补充。。。
shared_ptr相互引用,那么这两个指针的引用计数永远不可能降低为0,资源永远不会释放。
没法检测出循环引用,这会形成资源没法释放,从而致使内存泄露。
为了 fix 这个问题,C++11引入了另外一个智能指针:weak_ptr
weak_ptr是用来解决shared_ptr相互引用时的死锁问题,若是说两个shared_ptr相互引用,那么这两个指针的引用计数永远不可能降低为0,资源永远不会释放。它是对对象的一种弱引用,不会增长对象的引用计数,和shared_ptr之间能够相互转化,shared_ptr能够直接赋值给它,它能够经过调用lock函数来得到shared_ptr。
做用在于协助 shared_ptr 工做,可得到资源的观测权,像旁观者那样观测资源的使用状况。观察者意味着 weak_ptr 只对 shared_ptr 进行引用,而不改变其引用计数,当被观察的 shared_ptr 失效后,相应的 weak_ptr 也相应失效。
weak_ptr更像是shared_ptr的助手:
待补充。。。