shared_ptr和weak_ptr智能指针结合使用的一个实例
2016-10-29 20:21
701 查看
结合shared_ptr、weak_ptr一个实例
感觉这个例子很好, 结合了很多知识技术。这个实例功能是简单模拟实现std::vector<std::string> 部分功能。 (只是非常简单一些操作),当然也可以继续扩展,甚至扩展为模板,主要是用于学习。使用两个类实现,分别是StrBlob、StrBlobPtr。
StrBlob主要使用shared_ptr类对象来管理资源,StrBlobPtr主要使用weak_ptr类对象来管理资源。底层操作数据对象
学习点: (真心感觉这个例子很棒)
1、StrBlob跟StrBlobPtr的关系,基本上类似容器和迭代器的关系,很好将他们区分开来。
2、对内存资源的管理,非常巧妙。
3、对异常考虑
下面是本例的完整代码, 然后再简单分析一下自己理解。
verStr.h
以下是一个测试用例,从一个文件中读取字符串,将其保存再StrBlob中,再将其打印出来。
简单分析:(以下资源是指std::vector<std::string>)
shared_ptr、weak_ptr具体类型如下
我们知道,我们用StrBlob去显示初始化StrBlobPtr对象, 主要是使用data去初始化wptr
当构造完StrBlobPtr对象,shared_ptr所管理的资源用户是不会增加的(即资源引用计数不会自增一),weak_ptr只是指向一块被shared_ptr管理的资源,所拥有的这份资源的管理权在shared_ptr, 这也导致我们在使用weak_ptr所指向的资源的时候,需要检查一下它所指向的资源是否存在(因为shared_ptr所管理资源可能被删除)。
在StrBlobPtr中check中函数实现。当weak_ptr所指向的资源不存在时,便抛出一个异常runtime_error。
这里还有一个地方需要注意,weak_ptr是没有办法直接操作它所指向的资源的(一个原因是它所指向的资源有可能被删除),需要借助shared_ptr对象,通过调用wptr.lock(),当wptr指向非空时,返回一个shared_ptr对象,指向的wptr所指向的资源, 并用这个对象去初始化ret(创建了一个shared_pre对象名ret,这时候weak_ptr所返回的资源管理用户会增加多一个,即ret这个用户,资源引用计数增加一个)。如果wptr指向空,那么这时候lock会返回一个nullptr空指针,程序会抛出一个异常。
现在问题又来了,ret这个用户作为check函数的返回值,意味着ret这个用户并没有在check函数结束后释放对它所指向的资源的管理权(资源引用不会减少)那让我们来跟踪一个ret这个用户去哪里了。 StrBlobPtr类有deref、incr成员调用这个函数,如下。
显然当这两个函数分别执行完后,ret将作为函数中局部对象销毁了,这时候(资源引用计数递减1)。 非常巧妙,非常简单,这样便保证了资源不会泄漏。
在仔细看看,StrBlobPtr对象是如何解引用获取StrBlob对象的值,这里并不是在StrBlobPtr类中重载operator *实现解引用。而是使用了refef成员函数代替(为了方便),
容易看到是通过shared_ptr对象操作下标cur,取得了该资源(vector<string>)所对应的值( 相当于(*data)[cur]).
再来看看如何对StrBlobPtr对象实现递增,这里同样也不是重载operator ++()或者是operator ++(int) 分别对应前置递增跟后置递增, 这里使用incr()函数,结合数据成员
模拟实现前置递增,很容易看出来。
想想上述对象是否能够满足创建const StrBlob 和const StrBlobPtr 对象??
显然是不符合我们使用习惯,需要再重载如下函数:
在StrBlob中(以下只提供声明声明,实现类似)
在StrBlobPtr中
以上分析是个人理解,有不妥欢迎指出来。
参考:
C++Primer 5th (12.1.6 weak_ptr)
原文:http://blog.csdn.net/qq_33850438/article/details/52955326
感觉这个例子很好, 结合了很多知识技术。这个实例功能是简单模拟实现std::vector<std::string> 部分功能。 (只是非常简单一些操作),当然也可以继续扩展,甚至扩展为模板,主要是用于学习。使用两个类实现,分别是StrBlob、StrBlobPtr。
StrBlob主要使用shared_ptr类对象来管理资源,StrBlobPtr主要使用weak_ptr类对象来管理资源。底层操作数据对象
std::vector<std::string>
学习点: (真心感觉这个例子很棒)
1、StrBlob跟StrBlobPtr的关系,基本上类似容器和迭代器的关系,很好将他们区分开来。
2、对内存资源的管理,非常巧妙。
3、对异常考虑
下面是本例的完整代码, 然后再简单分析一下自己理解。
verStr.h
#ifndef VECSTR_H_INCLUDED #define VECSTR_H_INCLUDED #include<memory> #include<vector> #include<string> class StrBlobPtr; class StrBlob { public: using size_type = std::vector<std::string>::size_type; // in order to access the data member in StrBlobPtr class friend class StrBlobPtr; //constructor StrBlob() :data(std::make_shared<std::vector<std::string> >()) {} StrBlob(const std::initializer_list<std::string> lisStr) : data(std::make_shared<std::vector<std::string> >(lisStr)) {} //the operator of size size_type size() const{ return data->size();} bool empty() const { return data->empty();} //add and remove elements void push_back(const std::string& str) {data->push_back(str);} void pop_back() { check(0,"pop_back on empty StrBlob"); data->pop_back(); } //element access std::string& front() const { check(0,"front on empty StrBlob"); return data->front(); } std::string& back() const { check(0,"back on empty StrBlob"); return data->back(); } //return StrBlobPtr to the first and one past the last elements StrBlobPtr begin(); StrBlobPtr end(); private: std::shared_ptr<std::vector<std::string> > data; // throws msg if data[_size] isn't valid void check(size_type _size,const std::string& msg) const { if(_size>=data->size()) throw std::runtime_error(msg); } }; class StrBlobPtr { public: StrBlobPtr() :cur(0){} StrBlobPtr(StrBlob& str,std::size_t sz = 0) :wptr(str.data),cur(sz) { } // operator of elements bool operator!=(const StrBlobPtr& p) { return p.cur!= cur; } std::string& deref() const; StrBlobPtr& incr(); // prefix version private: std::shared_ptr<std::vector<std::string> > check(std::size_t ,const std::string& msg) const; //store a weak_ptr, which means the underlying vector might be destroyed std::weak_ptr<std::vector<std::string> > wptr; std::size_t cur; // current position within the array }; std::shared_ptr<std::vector<std::string> > StrBlobPtr::check(std::size_t _size,const std::string& msg) const { auto ret = wptr.lock(); //return the shared_ptr pointer to the object to which wptr points from lock to initialize ret if(!ret) throw std::runtime_error("unbound StrBlobPtr"); if(_size>=ret->size()) throw std::out_of_range(msg); return ret; } std::string& StrBlobPtr::deref() const { auto p = check(cur,"dereference past end"); return (*p)[cur]; } StrBlobPtr& StrBlobPtr::incr() { check(cur,"increment past end of StrBlobPtr"); ++cur; return *this; } StrBlobPtr StrBlob::begin() { return StrBlobPtr(*this); } StrBlobPtr StrBlob::end() { auto ret = StrBlobPtr(*this,data->size()); return ret; } #endif // VECSTR_H_INCLUDED
以下是一个测试用例,从一个文件中读取字符串,将其保存再StrBlob中,再将其打印出来。
#include <iostream> #include<fstream> #include<sstream> #include<algorithm> #include"vecStr.h" const std::string fileName = "input.txt"; int main() { StrBlob str; std::ifstream fs(fileName); std::string buffer; while(getline(fs,buffer)) str.push_back(buffer); for(StrBlobPtr it = str.begin();it!=str.end(); it.incr()) { std::cout<<it.deref()<<std::endl; } return 0; }
简单分析:(以下资源是指std::vector<std::string>)
shared_ptr、weak_ptr具体类型如下
std::shared_ptr<std::vector<std::string> > data; std::weak_ptr<std::vector<std::string> > wptr;
我们知道,我们用StrBlob去显示初始化StrBlobPtr对象, 主要是使用data去初始化wptr
StrBlobPtr(StrBlob& str,std::size_t sz = 0) :wptr(str.data),cur(sz) { }
当构造完StrBlobPtr对象,shared_ptr所管理的资源用户是不会增加的(即资源引用计数不会自增一),weak_ptr只是指向一块被shared_ptr管理的资源,所拥有的这份资源的管理权在shared_ptr, 这也导致我们在使用weak_ptr所指向的资源的时候,需要检查一下它所指向的资源是否存在(因为shared_ptr所管理资源可能被删除)。
在StrBlobPtr中check中函数实现。当weak_ptr所指向的资源不存在时,便抛出一个异常runtime_error。
std::shared_ptr<std::vector<std::string> > StrBlobPtr::check(std::size_t _size,const std::string& msg) const { auto ret = wptr.lock(); //return the shared_ptr pointer to the object to which wptr points from lock to initialize ret if(!ret) throw std::runtime_error("unbound StrBlobPtr"); if(_size>=ret->size()) throw std::out_of_range(msg); return ret; }
这里还有一个地方需要注意,weak_ptr是没有办法直接操作它所指向的资源的(一个原因是它所指向的资源有可能被删除),需要借助shared_ptr对象,通过调用wptr.lock(),当wptr指向非空时,返回一个shared_ptr对象,指向的wptr所指向的资源, 并用这个对象去初始化ret(创建了一个shared_pre对象名ret,这时候weak_ptr所返回的资源管理用户会增加多一个,即ret这个用户,资源引用计数增加一个)。如果wptr指向空,那么这时候lock会返回一个nullptr空指针,程序会抛出一个异常。
现在问题又来了,ret这个用户作为check函数的返回值,意味着ret这个用户并没有在check函数结束后释放对它所指向的资源的管理权(资源引用不会减少)那让我们来跟踪一个ret这个用户去哪里了。 StrBlobPtr类有deref、incr成员调用这个函数,如下。
std::string& StrBlobPtr::deref() const { auto p = check(cur,"dereference past end"); return (*p)[cur]; } StrBlobPtr& StrBlobPtr::incr() { check(cur,"increment past end of StrBlobPtr"); ++cur; return *this; }
显然当这两个函数分别执行完后,ret将作为函数中局部对象销毁了,这时候(资源引用计数递减1)。 非常巧妙,非常简单,这样便保证了资源不会泄漏。
在仔细看看,StrBlobPtr对象是如何解引用获取StrBlob对象的值,这里并不是在StrBlobPtr类中重载operator *实现解引用。而是使用了refef成员函数代替(为了方便),
容易看到是通过shared_ptr对象操作下标cur,取得了该资源(vector<string>)所对应的值( 相当于(*data)[cur]).
再来看看如何对StrBlobPtr对象实现递增,这里同样也不是重载operator ++()或者是operator ++(int) 分别对应前置递增跟后置递增, 这里使用incr()函数,结合数据成员
std::weak_ptr<std::vector<std::string> > wptr; std::size_t cur; // current position within the array
模拟实现前置递增,很容易看出来。
想想上述对象是否能够满足创建const StrBlob 和const StrBlobPtr 对象??
显然是不符合我们使用习惯,需要再重载如下函数:
在StrBlob中(以下只提供声明声明,实现类似)
StrBlobPtr begin() const ; StrBlobPtr end(); const;
在StrBlobPtr中
const std::string& deref() const;
以上分析是个人理解,有不妥欢迎指出来。
参考:
C++Primer 5th (12.1.6 weak_ptr)
原文:http://blog.csdn.net/qq_33850438/article/details/52955326
相关文章推荐
- C++:智能指针-TR1的shared_ptr和weak_ptr使用介绍
- C++:智能指针-TR1的shared_ptr和weak_ptr使用介绍
- boost库的智能指针shared_ptr结合容器vector的使用
- C++:智能指针-TR1的shared_ptr和weak_ptr使用介绍
- C++ Primer : 第十二章 : 动态内存之shared_ptr与new的结合使用、智能指针异常
- stl中auto_ptr,unique_ptr,shared_ptr,weak_ptr四种智能指针使用总结
- C++智能指针:TR1的 shared_ptr 和 weak_ptr 使用介绍
- stl中auto_ptr,unique_ptr,shared_ptr,weak_ptr四种智能指针使用总结
- c++智能指针(三)之shared_ptr和new结合使用
- C++智能指针 shared_ptr 与 weak_ptr 原理
- C++ 智能指针的一个实现(基于模板和Shared_ptr)
- 详解 boost 库智能指针(scoped_ptr<T> 、shared_ptr<T> 、weak_ptr<T> 源码分析)
- c++11之shared_ptr智能指针使用
- 智能指针:unique_ptr、shared_ptr、weak_ptr
- C++11新特性之智能指针(shared_ptr/unique_ptr/weak_ptr)
- C++智能指针shared_ptr的三种使用方式
- 智能指针tr1::shared_ptr、boost::shared_ptr使用
- C++11 Intro - C++11智能指针之shared_ptr、weak_ptr
- C++11新特性之智能指针(shared_ptr/unique_ptr/weak_ptr)
- boost::shared_ptr 智能指针在项目中的使用