练习12.19:定义你自己版本的StrBlobPtr,更新StrBlob类,加入恰当的friend声明及begin和end成员。
/*
*练习12.19
*2016/1/22
*问题描述:
练习12.19:定义你自己版本的StrBlobPtr,更新StrBlob类,加入恰当的friend声明及
begin和end成员。
*参考:http://blog.csdn.net/sunhero2010/article/details/49882993
*作者:Nick Feng
*邮箱:[email protected]
*/
/*
*练习12.7
*2015/11/2
*问题描述:
练习12.7:重做上一题,这次使用shared_ptr而不是内置指针。
练习12.6:编写函数,返回一个动态分配的int的vector。将此vector传递给另一个函数
,这个函数读取标准输入,将读入的值保存在vector元素中。再将vector
传递给另一个函数,打印读入的值。记得在恰当的时刻delete vector。
*说明:指针学习 fun(),fun2(),fun3() 分别实现三个函数的要求 ,和12.7不一样的
地方在于,只能指针的内存管理不要你烦了
*作者:Nick Feng
*邮箱:[email protected]
*/
#include
#include
#include
#include
#include
using namespace std;
class StrBlobPtr;
class StrBlob{
friend class StrBlobPtr;
public:
typedef std::vector<std::string>::size_type size_type;
StrBlob();
StrBlob(std::initializer_list<std::string> il);
size_type size() const { return data->size();}
bool empty() const { return data->empty();}
void push_back(const std::string &t) { data->push_back(t);}
void pop_back();
const std::string& front();
const std::string& back();
StrBlobPtr begin();
StrBlobPtr end();
private:
std::shared_ptr<std::vector<std::string>> data;
void check(size_type i, const std::string &msg) const;
};
StrBlob::StrBlob() : data(make_shared<vector<string>>()) { }
StrBlob::StrBlob(initializer_list<string> il) : data
(make_shared<vector<string>>(il)){ }
void StrBlob::check(size_type i, const string &msg) const
{
if(i >= data->size())
throw out_of_range(msg);
}
const string& StrBlob::front()
{
check(0,"front on empty StrBlob");
return data->front();
}
const string& StrBlob::back()
{
check(0,"back on empty StrBlob");
return data->back();
}
void StrBlob::pop_back()
{
check(0,"pop_back on empty StrBlob");
data->pop_back();
}
class StrBlobPtr{
friend bool eq(const StrBlobPtr&, const StrBlobPtr&);
public:
StrBlobPtr() : curr(0) { }
StrBlobPtr(StrBlob &a, size_t sz = 0) : wptr(a.data), curr
(sz) { }
std::string& deref() const;
StrBlobPtr& incr(); //前缀递增
private:
//若检查成功,check返回一个指向vector的shared_ptr
std::shared_ptr<std::vector<std::string>> check(std::size_t,
const std::string&) const;
//保存一个weak_ptr,意味着底层vector可能被销毁
std::weak_ptr<std::vector<std::string>> wptr;
std::size_t curr;//在数组中的当前位置
};
std::shared_ptr<std::vector<std::string>> StrBlobPtr::check(std::size_t i,
const std::string &msg) const
{
auto ret = wptr.lock(); //vector 还存在吗?
if(!ret)
throw std::runtime_error("unbound StrBlobPtr");
if(i >= ret->size())
throw std::out_of_range(msg);
return ret; //否则,返回指向vector的shared_ptr
}
std::string& StrBlobPtr::deref() const
{
auto p = check(curr,"dereference past end");
return (*p)[curr]; //(*p)是对象所指向的vector
}
//前缀递增:返回递增后的对象的引用
StrBlobPtr& StrBlobPtr::incr()
{
//如果curr 已经指向容器的尾后位置,就不能递增它
check(curr,"increment past end of StrBlobPtr");
++curr; //推进当前位置
return *this;
}
inline StrBlobPtr StrBlob::begin()
{
return StrBlobPtr(*this);
}
inline StrBlobPtr StrBlob::end()
{
auto ret = StrBlobPtr(*this, data->size());
return ret;
}
/*重载等于号*/
inline bool eq(const StrBlobPtr &lhs, const StrBlobPtr &rhs)
{
auto l = lhs.wptr.lock(), r = rhs.wptr.lock();
if (l == r)
return (!r || lhs.curr == rhs.curr);
else
return false;
}
/*重载不等于号*/
inline bool neq(const StrBlobPtr &lhs, const StrBlobPtr &rhs)
{
return !eq(lhs, rhs);
}
int main()
{
StrBlob b1;
{
StrBlob b2 = {"a", "an", "the"};
b1 = b2;
b2.push_back("about");
cout<cout<cout<" "<for (auto it = b1.begin(); neq(it, b1.end()); it.incr())
cout<return 0;
}
练习12.20:编写程序,逐行读入一个输入文件,将内容存入一个StrBlob中,用一个StrBlobPtr打印出StrBlob中的每个元素。
/*
*练习12.20
*2016/1/22
*问题描述:
练习12.20:编写程序,逐行读入一个输入文件,将内容存入一个StrBlob中,用一个
StrBlobPtr打印出StrBlob中的每个元素。
*参考:http://blog.csdn.net/sunhero2010/article/details/49882993
*作者:Nick Feng
*邮箱:[email protected]
*/
/*
*练习12.7
*2015/11/2
*问题描述:
练习12.7:重做上一题,这次使用shared_ptr而不是内置指针。
练习12.6:编写函数,返回一个动态分配的int的vector。将此vector传递给另一个函数
,这个函数读取标准输入,将读入的值保存在vector元素中。再将vector
传递给另一个函数,打印读入的值。记得在恰当的时刻delete vector。
*说明:指针学习 fun(),fun2(),fun3() 分别实现三个函数的要求 ,和12.7不一样的
地方在于,只能指针的内存管理不要你烦了
*作者:Nick Feng
*邮箱:[email protected]
*/
#include
#include
#include
#include
#include
using namespace std;
class StrBlobPtr;
class StrBlob{
friend class StrBlobPtr;
public:
typedef std::vector<std::string>::size_type size_type;
StrBlob();
StrBlob(std::initializer_list<std::string> il);
size_type size() const { return data->size();}
bool empty() const { return data->empty();}
void push_back(const std::string &t) { data->push_back(t);}
void pop_back();
const std::string& front();
const std::string& back();
StrBlobPtr begin();
StrBlobPtr end();
private:
std::shared_ptr<std::vector<std::string>> data;
void check(size_type i, const std::string &msg) const;
};
StrBlob::StrBlob() : data(make_shared<vector<string>>()) { }
StrBlob::StrBlob(initializer_list<string> il) : data
(make_shared<vector<string>>(il)){ }
void StrBlob::check(size_type i, const string &msg) const
{
if(i >= data->size())
throw out_of_range(msg);
}
const string& StrBlob::front()
{
check(0,"front on empty StrBlob");
return data->front();
}
const string& StrBlob::back()
{
check(0,"back on empty StrBlob");
return data->back();
}
void StrBlob::pop_back()
{
check(0,"pop_back on empty StrBlob");
data->pop_back();
}
class StrBlobPtr{
friend bool eq(const StrBlobPtr&, const StrBlobPtr&);
public:
StrBlobPtr() : curr(0) { }
StrBlobPtr(StrBlob &a, size_t sz = 0) : wptr(a.data), curr
(sz) { }
std::string& deref() const;
StrBlobPtr& incr(); //前缀递增
private:
//若检查成功,check返回一个指向vector的shared_ptr
std::shared_ptr<std::vector<std::string>> check(std::size_t,
const std::string&) const;
//保存一个weak_ptr,意味着底层vector可能被销毁
std::weak_ptr<std::vector<std::string>> wptr;
std::size_t curr;//在数组中的当前位置
};
std::shared_ptr<std::vector<std::string>> StrBlobPtr::check(std::size_t i,
const std::string &msg) const
{
auto ret = wptr.lock(); //vector 还存在吗?
if(!ret)
throw std::runtime_error("unbound StrBlobPtr");
if(i >= ret->size())
throw std::out_of_range(msg);
return ret; //否则,返回指向vector的shared_ptr
}
std::string& StrBlobPtr::deref() const
{
auto p = check(curr,"dereference past end");
return (*p)[curr]; //(*p)是对象所指向的vector
}
//前缀递增:返回递增后的对象的引用
StrBlobPtr& StrBlobPtr::incr()
{
//如果curr 已经指向容器的尾后位置,就不能递增它
check(curr,"increment past end of StrBlobPtr");
++curr; //推进当前位置
return *this;
}
inline StrBlobPtr StrBlob::begin()
{
return StrBlobPtr(*this);
}
inline StrBlobPtr StrBlob::end()
{
auto ret = StrBlobPtr(*this, data->size());
return ret;
}
/*重载等于号*/
inline bool eq(const StrBlobPtr &lhs, const StrBlobPtr &rhs)
{
auto l = lhs.wptr.lock(), r = rhs.wptr.lock();
if (l == r)
return (!r || lhs.curr == rhs.curr);
else
return false;
}
/*重载不等于号*/
inline bool neq(const StrBlobPtr &lhs, const StrBlobPtr &rhs)
{
return !eq(lhs, rhs);
}
int main()
{
ifstream in("test.txt");
if (!in) {
cout<<"Open input file failed"<return -1;
}
StrBlob b;
string s;
while (getline(in, s))
b.push_back(s);
for (auto it = b.begin(); neq(it, b.end()); it.incr())
cout<return 0;
}
练习12.21:也可以这样编写StrBlobPtr的deref成员:
std:string & deref() const
{ return (*check(curr,"dereference past end"))[curr];}
你认为哪个版本更好?为什么?
答书上的版本更好,分开写,清晰易于理解。
参考
http://blog.csdn.net/sunhero2010/article/details/49882993
练习12.22: 为了能让StrBlobPtr使用const StrBlob,你觉得应该如何修改?定义一个名为ConstStrBlobStr的类,使其能够指向const StrBlob。
答:对StrBlobPtr的构造函数做点修改即可
StrBlobStr(const StrBlob &a, size_t sz = 0) :wptr(a.data), curr(sz){}
参考:http://blog.csdn.net/chxw098/article/details/39035885