zoukankan      html  css  js  c++  java
  • c++ string类

    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;
    
  • 相关阅读:
    WPF 关于拖拽打开文件的注意事项
    asp.net core 3.1中对Mongodb BsonDocument的序列化和反序列化支持
    用百度webuploader分片上传大文件
    多线程学习笔记
    web.config数据库连接字符串加密
    Visual Studio 2010 常用快捷方式
    Team Foundation Server 2013 日常使用使用手册(四)分支与合并
    Team Foundation Server 2013 日常使用使用手册(三)上传新工程、创建任务、创建bug、设置预警
    Team Foundation Server 2013 日常使用使用手册(二)修改、签入、撤销、回滚、对比代码变更
    Team Foundation Server 2013 日常使用使用手册(一)-本地连接TFS、查看任务
  • 原文地址:https://www.cnblogs.com/yuandonghua/p/15635905.html
Copyright © 2011-2022 走看看