將StrVec類的一些變量進行全局替換就能得到String類
1、string替換爲char
2、str替換爲c,strs替換爲c
3、StrVec替換爲String
4、#include <string>替換爲#include<cstring>
StrVec和String就是類似的
1、都是保存指向元素的指針,指向的空間都是在內中動態分配的。
2、拷貝構造函數、拷貝賦值運算符拷貝StrVec(String)類的成員和指向的元素(拷貝賦值運算符有析構指向空間的過程)
3、析構函數都是析構指針指向的空間。
不同點:
reallocate:
StrVec:是移動原空間的數據到新空間,釋放原空間的string對象,不釋放string指向的char元素(移動後原string指向的空間爲nullptr)
String:移動char後,不會釋放char
原因是StrVec有兩層指向,最基礎的一層是不能銷燬的,否則移動到新空間的數據被銷燬了(這個地方還理解去清楚)
String.h
#include <cstring>
#include <memory>
#include <utility> // pair move
#include <initializer_list> // initializer_list
#include <algorithm> // for_each
#ifndef STRVEC__H
#define STRVEC__H
using namespace std;
class String {
public:
String():b(nullptr),e(nullptr),cap(nullptr){}
String(const char *);
String(const String &);
String(String &&);
String &operator=(const String &);
String &operator=(String &&);
~String();
void push_back(const char &);
size_t size() const {return e - b;}
size_t capacity() const {return cap - b;}
void reserve(const size_t &);
void resize(const size_t &);
void resize(const size_t &, const char &);
char *begin() const {return b;}
char *end() const {return e;}
private:
static allocator<char> alloc;
void chk_n_alloc() {if(size() == capacity()) reallocate();}
pair<char*,char*> alloc_n_copy(const char*, const char*);
void free();
void reallocate();
char *b;
char *e;
char *cap;
}
#endif
String.cpp
#include "String.h"
// 靜態成員變量定義和默認初始化。
// 靜態成員變量不屬於任何對象,不能在類的構造函數中被構造和初始化,必須在類的外部定義和初始化
// 不要重複寫static
// 靜態函數可以在類內部定義(沒有初始化一說)
allocator<char> String::alloc;
String::String(const initializer_list<char> &c) {
auto p = alloc_n_copy(c.begin(), c.end());
b = p.first;
e = cap = p.second;
}
String::String(const char *c) {
auto p = alloc_n_copy(c, c+strlen(c));
b = p.first;
e = cap = p.second;
}
pair<char*,char*> String::alloc_n_copy(const char *b_ptr, const char *e_ptr) {
auto p = alloc.allocate(e_ptr - b_ptr);
return {p, uninitialized_copy(b_ptr, e_ptr, p)};
}
void String::free() {
if(e) {
for(auto p = e; p != b;)
alloc.destroy(--p);
alloc.deallocate(cap-b);
}
}
void String::reallocate() {
size_t newcapacity = size() ? 2*size() : 1;
auto p = alloc.allocate(newcapacity);
auto dst = p;
auto src = b;
for(size_t i=0; i != size(); ++i)
alloc.construct(dst++, std::move(*src++));
b = p;
e = dst;// p + size();
cap = p + newcapacity;
}
String::String(const String &s) {
auto p = alloc_n_copy(s.begin(), s.end());
b = p.first;
e = cap = p.second;
}
String::String(String &&s):b(s.b), e(s.e), cap(s.cap) {// 要修改s的內部成員,所以不能爲const
s.b = s.e = s.cap = nullptr;
}
String &String::operator=(const String &s) {
auto p = alloc_n_copy(s.begin(), s.end());
free();
b = p.first;
e = cap = p.second;
}
String &String::operator=(String &&s) {// 要修改s的內部成員,所以不能爲const
if(this != &s) {
free();
b = s.b;
e = s.e;
cap = s.cap;
s.b = s.e = s.cap = nullptr;
}
return *this;
}
String::~String() {
free();
}
void String::push_back(const char &c) {
chk_n_alloc();
alloc.construct(e++, c);
}
void String::resize(const size_t &n) {
if(n > capacity()) {
auto p = alloc.allocate(n);
auto dst = p;
auto src = b;
size_t i = 0;
for(; i != size(); ++i)
alloc.construct(dst++, std::move(src++));
for(; i != n; ++i)
alloc.construct(dst++);
free();
b = p;
e = cap = dst;
} else if(n > size()) {
while(e < b+n)
alloc.construct(e++);
} else {
while(e > b+n)
alloc.destroy(--e);
}
}
void String::resize(const size_t &n, const char &c) {
if(n > capacity()) {
auto p = alloc.allocate(n);
auto dst = p;
auto src = b;
size_t i = 0;
for(; i != size(); ++i)
alloc.construct(dst++, std::move(src++));
for(; i != n; ++i)
alloc.construct(dst++, c);
free();
b = p;
e = cap = dst;
} else if(n > size()) {
while(e < b+n)
alloc.construct(e++, c);
} else {
while(e > b+n)
alloc.destroy(--e);
}
}
void String::reserve(const size_t &n) {
if(capacity() < n) {
auto p = alloc.allocate(n);
auto dst = p;
auto src = b;
for(size_t i=0; i<size(); ++i)
alloc.const(dst++, std::move(src++));
free();
b = p;
e = dst;
cap = b + n;
}
}
測試代碼 String.cpp
String str("hello");
for(const auto &v : str)
cout<<v
cout<<endl;
內容來源:https://www.cnblogs.com/yuandonghua/p/11508557.html