写在前言:这是一道C++primer第五版第十三章的习题,13.44,都是按自己的感觉写的,如有逻辑错误,请您不吝赐教!
进入正题:这个String支持标准库string的基础操作,比如+=操作、输出操作、size()函数、capacity()函数、begin()函数、end()函数。
从头分析,构造函数接受无参,也接受一个const char*的字符指针,ptr递增,指向str的尾部,相当于迭代器end()位置,调用alloac_begin_end函数,返回一个pair类型,first成员指向首,second成员指向尾。直接输出就调用<<重载函数,调用show()函数直接输出,如果进行+=操作,先判断容量的大小是否够新增的大小,如果不够,调用reallocat(),重新分配大小,用allocate重新构建,construct添加以前所保存的值,free()函数,释放之前所保留的内存空间。大致的思路就是这样的。
通过写这个String类,终于理解当初的困惑,destroy函数–first_free目的不是把first_free减到first的位置,而是为了销毁存储的元素,重新构建也和–first_frr减到first的位置无关,重建是用allocate重新分配大小,construct添加元素,进而完成重建。
#ifndef STRING_H_INCLUDED
#define STRING_H_INCLUDED
#include"dxgzg.h"
using std::allocator;
using std::cout;
using std::endl;
class String {
friend std::ostream& operator<<( std::ostream&out,String& s);//重载输出运算符,参数顺序不能改变
allocator<char>alloc;
char* first, * first_free, *end1;
void check_size(size_t num) {
if (size()+num>= capacity()) {
reallocat(num);
}
}
std::pair<char*, char*>alloc_begin_end(const char *c1,const char *c2) {
auto newdata = alloc.allocate(c2 - c1);
return { newdata,std::uninitialized_copy(c1,c2,newdata) };//unitialized_copy返回值类似迭代器end的位置
}
void reallocat(size_t num) {
size_t newcapacity =(capacity()!=0)?capacity()* 2+num:10;
auto newfirst = alloc.allocate(newcapacity);
auto newfirst_free = newfirst;
auto f = first;
for (auto it = begin(); it != end(); ++it) {
alloc.construct(newfirst_free++, *it);
}
free();//释放原先所指向的地址
first = newfirst;
first_free = newfirst_free;
end1 = first + newcapacity;
}
public:
String():first(nullptr),first_free(nullptr),end1(nullptr){}
String(const char *str) {
auto ptr = str;
while (*ptr!='\0') {//这样求出char*的字符串长度
++ptr;
}
auto pair_it = alloc_begin_end(str,ptr);
first = pair_it.first;
first_free = end1 = pair_it.second;
}
String(const String& s) {//this需要重新用allocate构建
auto newdata = alloc_begin_end(s.begin(), s.end());
this->first = newdata.first;
this->first_free = this->end1 = newdata.second;
}
String& operator=(const String& s) {
free();
auto newdata = alloc_begin_end(s.begin(), s.end());
this->first = newdata.first;
this->first_free = this->end1 = newdata.second;
return *this;
}
String& operator+=(const String &str) {
size_t num = str.size();
check_size(num);
for (auto it = str.begin(); it != str.end();++it) {
alloc.construct(this->first_free++,*it);
}
return *this;
}
~String() {
free();
}
void free() {
if (first) {
for (auto f = first_free; f != first;) {
alloc.destroy(--f);
}
alloc.deallocate(first,end1-first);
}
}
void show(){
for (auto it = begin(); it != end(); ++it) {
cout << *it;
}
}
char* begin()const{
return first;
}
char* end()const{
return first_free;
}
size_t size()const{
return first_free - first;
}
size_t capacity()const{
return end1 - first;
}
};
std::ostream& operator<<(std::ostream&out,String&s) {
s.show();
return out;
}
#endif // !STRING_H_INCLUDED