C++11标准引入了boost库中的智能指针,给C++开发时的内存管理提供了极大的方便。接下来这篇文件介绍shared_ptr/weak_ptr内部实现原理及使用细节。 C++不像java有内存回收机制,每次程序员new出来的对象需要手动delete,流程复杂时可能会漏掉delete,导致内存泄漏。于是C++引入智能指针,可用于动态资源管理,资源即对象的管理策略。 C++中的shared_ptr/weak_ptr和Android的sp/wp功能类似,都为解决多线程编程中heap内存管理问题而产生的。当程序规模较小时,我们可以手动管理new分配出来的裸指针,什么时候delete释放我们自己手动控制。 但是,当程序规模变大时,并且该heap内存会在各个线程/模块中进行传递和互相引用,当各个模块退出时,谁去释放?由此引入了智能指针的概念。 其原理可以概况为,内部通过引用计数方式,指示heap内存对象的生存周期,而智能指针变量作为一个stack变量,利用栈区变量由操作系统维护(程序员无法控制)的特点进行管理。 实现细节: 这样的东东(我们姑且称其为一个“类”,就像int/char/string为程序语言的内建类,我们也可以定义自己的类来使用)需要有什么特点? 1.这个类内部需要有个指针,就是保护那个经常犯错的裸指针:heap内存对象指针。 2.这个类能够代表所有类型的指针,因此必须是模板类。 3.根据需要自动释放其指向的heap内存对象,也即当这个“智能指针类对象”释放时,其内部所包含的heap内存对象根据需要进行释放,因此这个类对象只能是一个stack区的对象(如果是heap区的,我们还需要手动delete,而我们希望有个系统能帮我们去做的东西),另外一点,这个类内部还需要有个变量,用于指示内部的heap内存对象引用数量,以便决定是否释放该heap内存对象。 智能指针shared_ptr对象跟其它stack区对象一样有共同的特点——每次离开作用域时会自动调用析构函数进行内存回收。利用该特点,析构时检查其内部所引用的heap内存对象的引用数量进行操作:1.引用计数减一变为0时,则必须释放;2.减一后仍不为0,那么其内部的heap内存对象同时被别的智能指针引用,因此不能释放。 使用示例: 复制代码 1 #include 2 #include 3 #include 4 5 using namespace std; 6 7 class Person { 8 public: 9 Person() { 10 cout<<"Person ctor"< &p) { 22 father = p; 23 } 24 25 void setSon(shared_ptr &p) { 26 son = p; 27 } 28 29 void printName() { 30 cout<<"name: "< father; 36 shared_ptr son; 37 }; 38 39 void test0() 40 { 41 cout<<"---------test0 normal release begin---------"< sp_pf(new Person("zjz")); 44 shared_ptr sp_ps(new Person("zcx")); 45 46 cout<<"---------test0 normal release end---------\n"< sp_pf(new Person("zjz")); 54 shared_ptr sp_ps(new Person("zcx")); 55 56 cout<<"addr: "<<&sp_pf<setSon(sp_ps); 63 sp_ps->setFather(sp_pf); 64 65 cout<<"222 father use_count: "< sp_pf(new Person("zjz")); 76 shared_ptr sp_ps(new Person("zcx")); 77 78 cout<<"addr: "<<&sp_pf<setSon(sp_ps); 85 //sp_ps->setFather(sp_pf); 86 87 cout<<"222 father use_count: "<但可以使用lock获得一个可用的shared_ptr对象。 为什么要引入“弱引用”指针呢? weak_ptr和shared_ptr是为解决heap对象的“所有权”而来。弱引用指针就是没有“所有权”的指针。有时候我只是想找个指向这块内存的指针,但我不想把这块内存的生命周期与这个指针关联。这种情况下,弱引用指针就代表“我指向这东西,但这东西什么时候释放不关我事儿……” 使用区别: 首先,不要把智能指针和祼指针的区别看得那么大,它们都是指针。因此,我们可以把智能指针和祼指针都统称为指针,它们共同的目标是通过地址去代表资源。既然指针能代表资源,那么不可避免地会涉及资源的所有权问题。在选择具体指针类型的时候,通过问以下几个问题就能知道使用哪种指针了。 1.指针是否需要拥有资源的所有权? 如果指针变量需要绑定资源的所有权,那么会选择unique_ptr或shared_ptr。它们可以通过RAII完成对资源生命期的自动管理。如果不需要拥有资源的所有权,那么会选择weak_ptr和raw pointer,这两种指针变量在离开作用域时不会对其所指向的资源产生任何影响。 2.如果指针拥有资源的所有权(owning pointer),那么该指针是否需要独占所有权? 独占则使用unique_ptr(人无我有,人有我丢),否则使用shared_ptr(你有我有全都有)。这一点很好理解。 3.如果不拥有资源的所有权(non-owning pointer),那么指针变量是否需要在适当的时候感知到资源的有效性? 如果需要则使用weak_ptr,它可以在适当的时候通过weak_ptr::lock()获得所有权,当拥有所有权后便可以得知资源的有效性。 分类: 程序语言https://www.cnblogs.com/Dreaming-in-Gottingen/p/11409820.html