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() ? 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++, 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(5, "handsome"); cout << sv.size() << " " << sv.capacity() << endl; sv.resize(3); cout << sv.size() << " " << sv.capacity() << endl; sv.resize(6); cout << sv.size() << " " << sv.capacity() << endl; sv.reserve(20); sv.push_back("handsome"); cout << sv.size() << " " << sv.capacity() << endl; return 0; }
时间: 2024-10-27 17:04:39