【轉載】web 部署專題(一):Gunicorn執行與配置方法
阿新 • • 發佈:2021-11-28
string類
將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 str("hello");
for(const auto &v : str)
cout<<v
cout<<endl;