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

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

这是StrVec.h

#pragma once

#include<string>
#include<memory>
#include<initializer_list>
using namespace std; class StrVec
{
public:
StrVec():
elements(nullptr),first_free(nullptr),cap(nullptr){}
StrVec(initializer_list<string> iLStr);//构造函数,接受一个initializer_list<string>参数
StrVec(const StrVec&);
StrVec& operator=(const StrVec&);
~StrVec();
string& operator[](size_t n)const //重载下标运算符,用来实现TextQuery和QueryResult对StrVec的使用
{
return *(elements + n);
}
void push_back(const string&);
size_t size()const { return first_free - elements; }
size_t capacity()const { return cap - elements; }
string *begin()const { return elements; }
string *end()const { return first_free; }
void reserve(size_t n);//分配至少容纳n个元素的空间
void resize(size_t n);//调整容器的大小为n个元素。若n<size(),则多出的元素被丢弃
//若必须添加新元素,对新元素进行值初始化
void resize(size_t n,string str);//调整容器的大小为n个元素,任何新添加的元素都初始化为值str
private:
allocator<string> alloc;
void chk_n_alloc()
{
if (size() == capacity())
reallocate();
}
pair<string*, string*>alloc_n_copy(const string *, const string *);
void free();
void reallocate();
string *elements;
string *first_free;
string *cap;
}; void StrVec::push_back(const string &s)
{
chk_n_alloc();
alloc.construct(first_free++, s);
} pair<string*,string*>
StrVec::alloc_n_copy(const string *b, const 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() ? * size() : ;
auto newdata = alloc.allocate(newcapacity);
auto dest = newdata;
auto elem = elements;
for (size_t i = ;i != size();++i)
alloc.construct(dest++, move(*elem++));
free();
elements = newdata;
first_free = dest;
cap = elements + newcapacity;
} void StrVec::reserve(size_t n)//分配至少容纳n个元素的空间
{
if (n > capacity())//如果n大于capacity()才会从新分配空间
{
auto newdata = alloc.allocate(n);//重新分配n个空间,newdata为新分配的空间的首地址
auto dest = newdata;
auto elem = elements;
for (;elem != first_free;) //为新分配的空间调用construct来实现string的构造,采用move调用的是移动构造函数
alloc.construct(dest++, move(*(elem++)));
free(); //元素的移动完成,释放原有的空间
elements = newdata; //为指针赋予新的值
first_free = dest;
cap = elements + n;
}
else return;
} void StrVec::resize(size_t n)//调整容器的大小为n个元素。若n<size(),则多出的元素被丢弃
//若必须添加新元素,对新元素进行值初始化
{
if (n <= size()) //如果n<size()则,应该对n后面的所有已经构造的元素调用destroy(),即多出的元素被丢弃
{
for (;first_free != elements + n;)
alloc.destroy(--first_free);
}
else
{
if (n > capacity())
{
reserve(n); //因为n>capacity(),所以一定会分配新的空间
}
for (;first_free != elements + n;) //添加新的元素,对新的元素进行值初始化
alloc.construct(first_free++, string(""));
}
} void StrVec::resize(size_t n,string str)//调整容器的大小为n个元素,任何新添加的元素都初始化为值str {
if (n <= size()) //如果n<size()则,应该对n后面的所有已经构造的元素调用destroy(),即多出的元素被丢弃
{
for (;first_free != elements + n;)
alloc.destroy(--first_free);
}
else
{
if (n > capacity())
{
reserve(n); //因为n>capacity(),所以一定会分配新的空间
}
for (;first_free != elements + n;) //添加新的元素为str
alloc.construct(first_free++, str);
}
} StrVec::StrVec(initializer_list<string> iLStr)//构造函数,接受一个initializer_list<string>参数
{
auto newdata = alloc_n_copy(std::begin(iLStr), std::end(iLStr));//调用alloc_n_copy函数,返回一个pair<string*,string*>
elements = newdata.first; //pair的第一个元素为新分配空间的地址
first_free = cap = newdata.second; //pair的第二个元素为新分配空间的最后一个元素之后的地址
}

下面是主函数,用来验证程序的正确性

// 13.5.cpp : 定义控制台应用程序的入口点。
// #include "stdafx.h"
#define _SCL_SECURE_NO_WARNINGS
#include"StrVec.h"
#include<string>
#include<iostream>
#include<memory>
using namespace std; int main()
{
StrVec sv({ "li","dandan","is" });
cout << sv.size() << " " << sv.capacity() << endl;
sv.resize(, "handsome");
cout << sv.size() << " " << sv.capacity() << endl;
sv.resize();
cout << sv.size() << " " << sv.capacity() << endl;
sv.resize();
cout << sv.size() << " " << sv.capacity() << endl;
sv.reserve();
sv.push_back("handsome");
cout << sv.size() << " " << sv.capacity() << endl;
return ;
}

C++primer 练习13.39的更多相关文章

  1. C++primer 练习13.44

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

  2. 【C++ Primer 第13章】2. 拷贝控制和资源管理

    拷贝控制和资源管理 • 类的行为像一个值.意味着它应该有自己的状态,当我们拷贝一个像值得对象时,副本和原对象是完全独立的,改变副本不会对原对象有任何影响. • 行为像指针的类则共享状态.当我们拷贝一个 ...

  3. 【C++ Primer 第13章】1. 拷贝控制、赋值和销毁

    拷贝控制.赋值和销毁 如果一个构造函数的第一个参数是自身类的引用,且额外的参数都有默认值,则此构造函数是拷贝控制函数(拷贝构造函数不应该是explicit的). 如果我们没有为一个类定义拷贝构造函数, ...

  4. 【C++ Primer 第13章】3. 交换操作

    交换操作 class HasPtr { friend void swap(HasPtr &rhs, HasPtr &yhs); //其他成员定义 }; void swap(HasPtr ...

  5. [C++ Primer] : 第13章: 拷贝控制

    拷贝, 赋值与销毁 当定义一个类时, 我们显示地或隐式地指定在此类型的对象拷贝, 移动, 赋值和销毁时做什么. 一个类通过定义5种特殊的成员函数来控制这些操作, 包括: 拷贝构造函数, 拷贝赋值运算符 ...

  6. C++ primer chapter 13

    拷贝 赋值 销毁 拷贝构造函数 如果一个构造函数第一个参数是自身的引用,而且任何额外参数都有默认值,则此构造函数是拷贝构造函数拷贝构造函数的第一个类型必须是引用:如果参数不是引用类型,那么调用不会成功 ...

  7. C++primer 练习13.36

    #pragma once #include<string> #include<set> using namespace std; class Message { friend ...

  8. 【C++ Primer 第13章】6.对象移动

    右值引用 左值和右值 (1)两者区别: ①左值:能对表达式取地址.或具名对象/变量.一般指表达式结束后依然存在的持久对象. ②右值:不能对表达式取地址,或匿名对象.一般指表达式结束就不再存在的临时对象 ...

  9. 【C++ Primer 第13章】5. 动态内存管理类

    StrVec类的设计 [题目描述]:我们将实现标准库vector类的一个简化版本,我们所做的一个简化是不使用模板,我们类只用于string,因此,它被命名为StrVec. #include<io ...

随机推荐

  1. 【转】Win7注册表的使用(更新中)

    一.注册表的存储结构和数据类型 1.基本概念: Windows 7的注册表主要由“键”和“键值”构成,称HKEY为根键(RootKey),SubKey为子键. 键(Key):“位于左侧窗格如同文件夹图 ...

  2. python3抓取异步百度瀑布流动态图片(一)查找post并伪装头方法

    打开流程: 用火狐打开百度图片-->打开firebug-->输入GIF图-->搜索-->点击网络-->全部 观察页面: 首先要观察的对象是“域”,图片的json一般是放在 ...

  3. C#接口作用的深入理解

    1.C#接口的作用 C#接口是一个让很多初学C#者容易迷糊的东西,用起来好像很简单,定义接口,里面包含方法,但没有方法具体实现的代码,然后在继承该接口的类里面要实现接口的所有方法的代码,但没有真正认识 ...

  4. jquery 设置select 默认值

    $('#@(Perfix)OrgType').children("option").each(function () { var temp_value = $(this).val( ...

  5. POJ #2479 - Maximum sum

    Hi, I'm back. This is a realy classic DP problem to code. 1. You have to be crystal clear about what ...

  6. jQuery制作视频网站的展示效果

    效果:如图所示,用户可以单击左上角的左右箭头,来控制视频展示的左右滚动. 当单击向右箭头时下面的展示视频会向左滚动隐藏,同时新的视频展示会以滚动方式显示出来.向左同理. css: ;; word-br ...

  7. 剑指offer系列37----数据流中的中位数

    [题目]如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值, * 那么中位数就是所有数值排序之后位于中间的数值. package com.exe8.offer; import java.uti ...

  8. IIS SMTP Queue stuck

    1. review smtp logs in C:\Windows\System32\LogFiles\SMTPSVC1, 2. find 421 error 2014-12-08 02:02:40 ...

  9. golang自动导入postgresql脚本

    直接代码 package main import ( "fmt" "golang-objective-go/dataFoundation/dataConvert" ...

  10. Hierarchy Viewer

    http://blog.csdn.net/ddna/article/details/5527072 Hierarchy Viewer是随AndroidSDK发布的工具,位置在tools文件夹下,名为h ...