《C++ Primer》第13章 拷贝控制

13.5节 动态内存管理类 习题答案

练习13.39:编写你自己版本的StrVec,包括自己版本的reserve、capacity(参见9.4节,第318页)和resize(参见9.3.5节,第314页)。

【出题思路】

本题练习设计自己管理内存的类。

【解答】

#ifndef STRVEC13_39_H
#define STRVEC13_39_H#include <string>
#include <memory>
#include <utility>class StrVec
{
public:StrVec(): elements(nullptr), first_free(nullptr), cap(nullptr){}StrVec(const StrVec&);StrVec& operator=(const StrVec&);~StrVec();void push_back(const std::string &);size_t size() const{return first_free - elements;}size_t capacity() const{return cap - elements;}std::string *begin() const{return elements;}std::string *end() const{return first_free;}void reserve(size_t count);//重分配容量void resize(size_t);//重置元素个数private:std::allocator<std::string> alloc;//分配元素void chk_n_alloc(){if(size() == capacity())reallocate();}std::pair<std::string *, std::string *> alloc_n_copy(const std::string *, const std::string *);void free();void reallocate();std::string *elements;      //分配的内存中的首元素std::string *first_free;    //最后一个实际元素之后的位置std::string *cap;           //分配的内存末尾之后的位置
};#endif // STRVEC13_39_H
#include "StrVec13_39.h"
#include <iostream>
#include <vector>
#include <utility>void StrVec::push_back(const std::string &s)
{chk_n_alloc();alloc.construct(first_free++, s);
}std::pair<std::string *, std::string *> StrVec::alloc_n_copy(const std::string *b, const std::string *e)
{auto data = alloc.allocate(e - b);return {data, uninitialized_copy(b, e, data)};
}void StrVec::free()
{if(elements){for(auto p = first_free; p != elements;)alloc.destroy(--p);alloc.deallocate(elements, cap - elements);}
}StrVec::StrVec(const StrVec &s)
{auto newdata = alloc_n_copy(s.begin(), s.end());elements = newdata.first;first_free = cap = newdata.second;
}StrVec::~StrVec()
{free();
}StrVec &StrVec::operator=(const StrVec &rhs)
{auto data = alloc_n_copy(rhs.begin(), rhs.end());free();elements = data.first;first_free = cap = data.second;return *this;
}void StrVec::reallocate()
{auto newcapacity = size() ? 2 * size() : 1;auto newdata = alloc.allocate(newcapacity);auto dest = newdata;auto elem = elements;for(size_t i = 0; i != size(); ++i)alloc.construct(dest++, std::move(*elem++));free();elements = newdata;first_free = dest;cap = elements + newcapacity;
}void StrVec::reserve(size_t count)
{if(size() < count){auto newdata = alloc.allocate(count);auto dest = newdata;auto elem = elements;for(size_t i = 0; i != size(); ++i)alloc.construct(dest++, std::move(*elem++));free();elements = newdata;first_free = dest;cap = elements + count;}
}void StrVec::resize(size_t count)
{if(count < size()){for(auto iter = elements + count; iter != first_free; ++iter)alloc.destroy(iter);first_free = elements + count;}if(count > size()){for(size_t i = 0; i != count - size(); ++i)alloc.construct(first_free++, std::string());}
}int main()
{StrVec vec;vec.push_back("scott");vec.push_back("camle");vec.push_back("星期六");vec.push_back("十月");vec.push_back("李河");vec.push_back("何乐而不为呢");std::cout << "strVec=====================size==" << vec.size() << std::endl;return 0;
}

运行结果:  strVec=====================size==6

练习13.40:为你的StrVec类添加一个构造函数,它接受一个initializer_list<string>参数。

【出题思路】

本题练习设计列表初始化。

【解答】

通过begin和end获得列表的整个范围,利用辅助函数alloc_n_copy分配足够多的空间,并将范围中的元素拷贝过去即可:

StrVec::StrVec(std::initializer_list<std::string> il)
{//调用alloc_n_copy分配与列表il中元素数目一样多的空间auto newdata = alloc_n_copy(il.begin(), il.end());elements = newdata.first;first_free = cap = newdata.second;
}

练习13.41:在push_back中,我们为什么在construct调用中使用后置递增运算?如果使用前置递增运算的话,会发生什么?

【出题思路】

理解几个指针的含义。

【解答】

因为first_free指向第一个空闲位置,也就是最后一个string的尾后位置。当添加新string时,应该保存在first_free指向的位置,然后将first_free推进一个位置,因此后置递增运算恰好符合要求。

如果使用前置递增运算,则是先将first_free推进一个位置,然后将新string保存在新位置上。显然,这种方法意味着first_free指向最后一个string,而非尾后位置,与first_free的设定不吻合。

练习13.42:在你的TextQuery和QueryResult类(参见12.3节,第431页)中用你的StrVec类代替vector<string>,以此来测试你的StrVec类。

【出题思路】

练习StrVec的使用。

【解答】

对TextQuery.h、QueryResult.h和TextQuery.cpp做如下修改:

1. TextQuery.h中file成员的定义改为:
    std::shared_ptr<StrVec> file; //输入字体
2. QueryResult.h中file成员的定义改为:
    std::shared_ptr<StrVec> file;
构造函数的第三个参数改为:std::shared_ptr<StrVec> get_file() {return file;}
3.TextQuery.cpp中构造函数初始化file成员的操作改为:
    TextQuery::TextQuery(ifstream &is):file(new StrVec)

与第12章的练习类似,由于类的封装特性,主程序不用进行任何修改。

练习13.43:重写free成员,用for_each和lambda(参见10.3.2节,第346页)来代替for循环destroy元素。你更倾向于哪种实现,为什么?

【出题思路】

复习lambda的定义和使用。

【解答】

将for循环改成如下形式即可。注意,elements和first_free是string*类型,因此它们指出的范围中的元素是string类型。因此,lambda的参数s应该是string&类型,在lambda的函数体中应该取s的地址,用来调用destroy。

for_each(elements, first_free, [this](std::string &s) {alloc.destory(&s);});
作者倾向于for_each和lambda版本,因为这个版本只需指出范围及对范围中元素执行什么操作即可,而for版本则需程序员小心控制指针的增减。

练习13.44:编写标准库string类的简化版本,命名为String。你的类应该至少有一个默认构造函数和一个接受C风格字符串指针参数的构造函数。使用allocator为你的String类分配所需内存。

【出题思路】

本题练习定义自己管理内存的类。

【解答】

总体上需要注意的地方与StrVec的定义类似,只不过StrVec管理的元素为string,而String管理的元素为char。配套网站已有完整程序,读者可以尝试自己定义String,然后与配套网站中的代码进行对照。

《C++ Primer》第13章 13.5节习题答案相关推荐

  1. 《C++ Primer》第14章 14.3节习题答案

    <C++ Primer>第14章 操作重载与类型转换 14.3节  算术和关系运算符  习题答案 练习14.13:你认为Sales_data类还应该支持哪些其他算术运算符(参见表4.1,第 ...

  2. 《C++ Primer》第9章 9.3节习题答案

    <C++ Primer>第9章 顺序容器 9.3节顺序容器操作习题答案 练习9.18:编写程序,从标准输入读取string序列,存入一个deque中.编写一个循环,用迭代器打印deque中 ...

  3. 《C++ Primer》第15章 15.4节习题答案

    <C++ Primer>第15章 面向对象程序设计 15.4节 抽象基类 习题答案 练习15.15:定义你自己的Disc_quote和Bulk_quote. [出题思路]本题练习实现不同折 ...

  4. 《C++ Primer》第15章 15.2节习题答案

    <C++ Primer>第15章 面向对象程序设计 本章介绍了面向对象程序设计的两个重要概念:继承和动态绑定,包括: □●继承.基类.派生类的基本概念. □●虚函数和虚基类. □●继承中的 ...

  5. 《C++ Primer》第12章 12.3节习题答案

    <C++ Primer>第12章 动态内存 12.3节使用标准库:文本查询程序 习题答案 练习12.27:TextQuery和QueryResult类只使用了我们已经介绍过的语言和标准库特 ...

  6. 《C++ Primer》第5章 5.2节习题答案

    <C++ Primer>第5章 语句 5.2节 语句作用域 练习5.4:说明下列例子的含义,如果存在问题,试着修改它. (a)while(string::iterator iter != ...

  7. C++ Primer - 5th Edition - 书中源代码 - 课后习题答案

    C++ Primer - 5th Edition - 书中源代码 - 课后习题答案 C++ Primer - 5th Edition - 书中源代码 - 课后习题答案 1. C++ Primer, 5 ...

  8. 浙大版《C语言程序设计》第四版(何钦铭颜晖) 第4章 循环结构 课后习题答案

    浙大版<C语言程序设计>第四版(何钦铭颜晖) 第4章 循环结构 课后习题答案 你也可以上程序咖(https://meta.chengxuka.com),打开大学幕题板块,不但有答案,讲解, ...

  9. matlab第三章题目,第3章 MATLAB矩阵处理习题答案

    <第3章 MATLAB矩阵处理习题答案>由会员分享,可在线阅读,更多相关<第3章 MATLAB矩阵处理习题答案(3页珍藏版)>请在人人文库网上搜索. 1.第3章 MATLAB矩 ...

  10. 软件工程 科学出版社 郑逢斌主编 第1章 软件工程概述 课后习题答案

    软件工程 科学出版社 郑逢斌 第1章 软件工程概述 课后习题答案 1. 简述软件的发展过程. 2. 简述软件的定义和特点. 定义: 在 IEEE 软件工程词汇标准中,软件的定义是:软件是计算机程序.规 ...

最新文章

  1. Nature Protocols | 密歇根州立大学何胜阳/Tiedje团队建立拟南芥微生物组研究的标准化生长体系!...
  2. Forcepoint DLP解决方案持续推高各机构的业务发展进程
  3. 降低百倍时间步,精度媲美传统神经网络:上交等机构提出ANN-SNN转换框架
  4. 使用rman本机复制新数据库
  5. 打印一个整数二进制表示中所有的奇数位和偶数位
  6. Qt工作笔记-使用SQL中的LIMIT进行数据分页
  7. 主成分分析法案例_机器学习理论(五)主成分分析法
  8. hdoj1102 Constructing Roads(Prime || Kruskal)
  9. mysql时间加减运算
  10. 【Excel】数据处理与查看
  11. springboot springsecurity报错 **.LoginUser cannot be cast to **.LoginUser
  12. 微信开发者工具控制台空白问题解决方案
  13. Twitter爬虫Python库Tweepy 附中英文官方文档
  14. pyspark:ML和MLlib
  15. vue2.6.11版本源码运行报错问题处理
  16. php导入excel 代码,php excel 导入导出源代码
  17. BrandTech如何提高种草爆文率?
  18. SolidWorks打开step格式后零件名变成下划线的解决方法
  19. EI从投稿到录用一般得多久?
  20. 电子元器件图片、名称、符号图形对照(精编请收藏)

热门文章

  1. 12月25日服务器例行维护公告,12月23日服务器例行维护公告
  2. 荣耀9x鸿蒙2.0,荣耀9X升级鸿蒙2.0系统截图曝光:4G内存流畅度照样起飞!
  3. 程序员之间的搞笑对话!测试妹子弄得大家好尴尬!
  4. 【jiasuba】鲜为人知的Word双行合一设置
  5. 探究无bom头的txt文件在打开时获取编码的方式
  6. 怎样运用KeyShot中材质采样值
  7. mysql中字符串转数字
  8. URL、URI、域名
  9. python绘制图形微格课_智慧职教MOOCPython程序设计章节测试答案
  10. ZYNQ使用1G/2.5G Ethernet PCS/PMA or SGMII拓展PS端网口