当前位置:网站首页>boost库智能指针

boost库智能指针

2022-08-02 14:07:00 lq_fly_pig

程序的内存资源管理一直是个比较麻烦的问题,c++程序在引入智能指针之前,new出来的内存,需要自己手动的销毁,自己去管理申请堆内存的生命周期。有的时候难免会遗漏对资源的释放销毁。智能指针则能很好的解决内存管理的问题,不但能很好的管理裸指针,还能管理内存资源(RAII)机制。前借助Boost库开发指南,这里做个简单的讲解。有不足地方请广大读者提出,感激不尽。
c++ 智能指针有比较多的版本,其中比较出名的是c++98中的std::auto_ptr指针。
auto_ptr 的构造函数接受new 操作符,或者对象工厂创建出的对象指针作为参数输入。退出作用域时会调用auto_ptr的析构函数,使用delete操作符删除原始指针释放资源。使用比较简单,
class CFG_Res; //资源类
void test1()
{
    auto_ptr<CFG_Res> p1(new CFG_Res);
    auto_ptr<CFG_Res> p2(factory.create());
}

和auto_ptr比较类似的一个智能指针是scoped_ptr,从名字可以看出来该指针是在被声明的作用域内使用,scoped_ptr类摘要中看出来,其构造函数和赋值操作符都是定义为private,禁止对指针进行复制,由于operator*() 和operator->()重载了指针的解引用操作,故可以使用*ptr 和ptr-> 操作符,下面贴一段书上的示例程序。

struct posi_file{
    posi_file(const char* file_name){
        cout << "---open the file ---" << endl; 
    }
    ~posi_file(){
        cout << " close the file ...." << endl;
    }
};
int main()
{
    scoped_ptr<int> p(new int);//一个int 类型的指针
    if(p){
        *p = 100;
        cout << *p << endl;//解引用操作
    }
    p.reset();
    assert(p==0);
    if(!p){
        cout << "  ptr is null  " << endl;
    }
    scoped_ptr<posi_file> fp(new posi_file("./aa.txt"));
    return 0;
}

auto_ptr和scoped_ptr 同样的缺陷不能作为容器的元素。前者是因为他的转移语义,后者是因为不支持拷贝和赋值,不符合容器对元素的类型要求。
shared_ptr也可以像上面两种智能指针一样可以包装new操作符在堆上分配的内存对象,主要的不同是其实现了内存的引用计数,改指针可以自由的被赋值和拷贝,在任何地方共享使用,当不使用改内存时,指针的引用计数为0,会自动的删除被包装的动态分配的内存。shared_ptr也可以安全的放入到标准库的容器中。
下面看看其类的成员函数。
(1).template <class Y> explicit shared_ptr(Y* p);
    构造函数获取指针p 的所有权,但是p 指针一定是能指向Y的有效指针,构造后引用计数为1。
(2).template <class Y,class D> shared_ptr(Y* p,D d); 
    构造函数带有两个参数,第一个是需要管理的指针p,第二个是引用计数为0 ,需要释放的资源对象,释放资源的对象是以d(p)的形式传给对象
(3).shared_ptr(const shared_ptr& r); 
    从另外一个shared_ptr获取指针管理权,同时引用计数加1,结果是两个shared_ptr管理一个指针对象资源。
(4).shared_ptr();
    无参数构造,创建一个持有空指针的shared_ptr指针。
(5).operator= 赋值操作符可以从另外一个shared_ptr或者auto_ptr获取指针的管理权,引用计数置为1,同时auto_ptr会失去管理权。
(6).~shared_ptr(); 
    析构函数对引用计数减1,如果引用计数为 0,则会删除被保存的指针对象,达到销毁资源的目的,同时,如果自己定义自定义删除器,则会调用自己定义的函数,按照定义的要求来释放资源。
(7).void reset();
    停止对保存的指针的所有权的共享,引用计数减1.
(8).bool unique() const; 
    shared_ptr是其保存指针的唯一的管理者是返回true.
(9).long use_count() const; 
    use_count 函数返回指针的引用计数,有的时候 这个操作是昂贵的,
(10).void swap(shared_ptr<T>& b); 
    交换两个指针的shared_ptr,同时指针和引用计数也会交换。

下面来看一个简单的示例:

#include <string>
#include <iostream>
#include <boost/shared_ptr.hpp>


class implementation
{
public:
    ~implementation() { std::cout <<"destroying implementation\n"; }
    int do_something() 
	{ 
		std::cout << "did something\n"; 
		return 111;
	}
};

typedef boost::shared_ptr<implementation> imple_; //智能指针
void test(){
	//imple_  sp1(new implementation());
	imple_ sp1; //构造一个空指针的shared_ptr
    sp1 = boost::shared_ptr<implementation> (new implementation());
	//sp1.reset(new implementation());//sp1之前管理的对象指针引用计数减1,现在开始管理新new出来的指针对象
    //boost::shared_ptr<implementation> sp1(new implementation());
	sp1->do_something();
    std::cout<<"The Sample now has "<<sp1.use_count()<<endl;
    //std::cout << "--result---" << sp1->do_something() << std::endl;
    boost::shared_ptr<implementation> sp2 = sp1;
   // std::cout<<"The Sample now has "<<sp2.use_count()<<" references\n";
    
    sp1.reset();//引用计数减1
    //std::cout<<"After Reset sp1. The Sample now has "<<sp2.use_count()<<" references\n";
    sp2.reset();
    //std::cout<<"After Reset sp2.\n";
}

int main()
{
    test();
    return 0;
}

weak_ptr 是"弱"指针,被设计和shared_ptr 共同工作,可以从一个shared_ptr 或者weak_ptr 获取构造,获得资源的观测权。
但是没有资源的共享权,不会引起资源的引用计数加1,同理在析构的时候 也不会引起资源的引用计数减1,它只是一个安静的观察者。
成员函数如下:
(1).use_count()  观测资源的引用计数。
(2).expired()  bool类型,true表示资源 已经不存在了,相当于 use_count()==0的结果
(3).lock() 是其很重要的一个成员函数。获取 观测资源可用的一个shared_ptr对象,由于没有重载operator*() 和
operator->()操作符,故只能通过shared_ptr对象来操作资源。
(4).expired()== true lock函数返回一个存储空指针的shared_ptr

一般是配合shared_ptr解决循环引用问题,下面看一个例子,这个例子也是从广大的网友那里找来的,这里只是借鉴学习下:

#include <iostream>
#include <boost/shared_ptr.hpp>
#include <boost/weak_ptr.hpp>

/**循环引用的问题**/
using namespace std;
using boost::shared_ptr;
using boost::weak_ptr;
class B;
class A;
class A
{
        public:
                A(){
                    cout << "A constructor~~" << endl;
                }
                
                ~A(){
                    cout << "A deconstructor~~" << endl;
                }
        public:
            shared_ptr<B> m_b;
};
class B
{
        public:
                B(){
                    cout << "B constructor~~" << endl;
                }
                
                ~B(){
                    cout << "B deconstructor~~" << endl;
                }
       public:
            shared_ptr<A> m_a;
};
class WA;
class WB;

class WA{
        public:
                WA(){
                    cout << "WA constructor~~" << endl;
                }
                
                ~WA(){
                    cout << "WA deconstructor~~" << endl;
                 }
        public:
            weak_ptr<WB> m_b;
};
class WB{
        public:
                WB(){
                    cout << "WB constructor~~" << endl;
                }
                ~WB(){
                    cout << "WB deconstructor~~" << endl;
                }
        public:
            weak_ptr<WA> m_a;
};

void test1()
{
    shared_ptr<A> aptr(new A);
    shared_ptr<B> bptr(new B);
    aptr->m_b = bptr;
    bptr->m_a = aptr;
    
}
void test2()
{
    shared_ptr<WA> waptr(new WA);
    shared_ptr<WB> wbptr(new WB);
    waptr->m_b = wbptr;
    wbptr->m_a = waptr;
    
}
int main()
{
  test1();//存在循环引用问题,资源不会析构
  test2();//离开作用域,资源会释放
}

 

 

原网站

版权声明
本文为[lq_fly_pig]所创,转载请带上原文链接,感谢
https://blog.csdn.net/lq_fly_pig/article/details/89601292