模拟实现string,vector,list(双向链表)问题反思

string的模拟实现

简述:模拟实现中,复现了文档里面的运算符重载,完成了iterator(迭代器)的实现,完成了字符(以及字符串)查找和插入,实现基本的拷贝构造,赋值重载。
对自己实现过程中遇见的问题做出几个标记。
名字都保证和C++标准网站的命名一致,实现相同或者相类似的功能。

reserve:这个函数的任务是扩容,参考g++编译器下面的实现,我也用了二倍扩容的方法,这里需要注意多留下一个空间方便放’\0’;

void reserve(size_t n)
            {
            	_capacity= _capacity==0 ? 4:_capacity*2;//_capacity是容量,指容纳的有效字符个数
                while(n>_capacity)
                {
                    _capacity*=2;
                } 
                char* t = new char[_capacity+1];//存n+1放下\0
                    strcpy(t,_str);//会拷贝\0给
                    delete []_str;
                    _str = t;
            }

[](下标解引用运算符)的重载
:这个基本上值得注意的不多,就是实现两个,方便外面传const型的string时,里面因权限延展的报错。

			char& operator[](size_t pos)
            {
                assert(pos<_size);
                return _str[pos];
            }
            const char& operator[](size_t pos)const
            {
                assert(pos<_size);
                return _str[pos];
            }

swap
:算法库里面实现的需要拷贝一次临时对象,消耗太大(调用赋值拷贝那些),根据底层,我们就可以自己写一个。
只需要交换底层的指针和内部变量就可以了。

			void swap(string & s)
            {
                std::swap(_str,s._str);
                std::swap(_capacity,s._capacity);
                std::swap(_size,s._size);
            }

= 赋值运算符重载
:再有了基本的构造函数和交换内存之后,这就变得很简单,新建一个tmp,交换内部的内容即可。

 string& operator=(const string& s)
            {
                if(this != &s)
                {
                    string tmp(s._str);//传一个字符串去构造,也可以直接调用拷贝构造
                    swap(tmp);//交换内存就完成了。
                }
                return *this;
            }

拷贝构造
:拷贝构造就是类似的道理

string(const string& s)
            :_size(0),
            _capacity(0),
            _str(new char[1]{0})
            {
                string tmp(s._str);
                swap(tmp);
            }
            

<< (流插入) >> (流提取)的运算符重载
:首先整个函数是在类外面实现的,原因是在类里面的话只能、string s; s<<cout; 这种写法就很奇怪,为了符合习惯(或者说是规范),因此我们就只能在外面重载。

ostream& operator<<(ostream& out,const string& s)
    {
        for(int i=0;i<s.size();i++)
        {
            out<<s[i];
        }
        return out;
    }
    istream& operator>>(istream& in,string& s)
    {
        // s.clear();
        // char t = 0;
        // t = in.get();
        // while(t!=' ' && t!= '\n')//涉及多次重扩展内存
        // {
        //     s.push_back(t);
        //     t = in.get();
        // }
        // return in;

        //利用缓冲区的思维
        s.clear();
        char arr[256];
        size_t i =0;
        char ch = in.get();
        while(ch != ' ' && ch!= '\n')
        {
            arr[i++] = ch;
            if(i == 255)
            {
                arr[i] = 0;
                s += arr;
                i = 0;
            }
            
            ch = in.get();
        }
        arr[i] = 0;
        s += arr;
        return in;
    }

iterator(迭代器)
:因为底层就是连续的物理空间,直接以指针作为迭代器即可。

iterator begin()
            {
                return _str;
            }
            iterator end()
            {
                return _str+_size;
            }
            iterator begin()const//对应const string 的迭代器
            {
                return _str;
            }
            iterator end()const
            {
                return _str+_size;
            }

vector

vector基本类似,是以三个指针去实现的,但是在构造函数的模板处有些不同。
以下两个构造函数,在是vector<int> a(10,0);就会报错,原因是10,和0都是整形,显然更适合的是模板那个函数。
因此为了解决这一点,加上第三份函数基本就没问题了。

template <class Inputiterator>//放入的迭代器区间。
            vector(Inputiterator first,Inputiterator end)
            :_start(nullptr)
            ,_finish(nullptr)
            ,_endOfStorage(nullptr)
            {
                while(first<end)
                {
                    push_back(*first++);
                }
            }
vector(size_t n,const T& val = T())
            :_start(nullptr)
            ,_finish(nullptr)
            ,_endOfStorage(nullptr)
            {
                while(size()<n)
                {
                    push_back(val);
                }
            }
vector(int n,const T& val = T())
            :_start(nullptr)
            ,_finish(nullptr)
            ,_endOfStorage(nullptr)
            {
                while(size()<n)
                {
                    push_back(val);
                }
            }

reserve
这里扩容需要拷贝原数据,不要直接用memcpy,不然就是在传string就会造成对空间的浅拷贝。

void reserve(size_t n)
            {
                if(n>capacity())
                {
                    size_t _capacity = n;
                    T* tmp = new T[_capacity];
                    int _size = size();
                    if(_start)
                    { 
                        copy(tmp,_start,_finish -_start);
                        delete[]_start;
                    }
                    _start = tmp;
                    _finish = _start+_size;
                    _endOfStorage = _start +_capacity;
                }
            }
            void copy(iterator dest,const  iterator& sor,size_t n)
            {
                for(int i = 0;i<n;i++)
                {
                    dest[i] = sor[i];
                }
            }

list

知道了底层双向链表的规律,整日实现是比较简单的。
这里说下迭代器的封装。


	//前置声明
	template <typename T>
    class list;

	//迭代器里面需要链表类,链表类需要迭代器,双向依赖
	//解决:前置声明:在两个之前,声明后面个类。
	//告诉编译器有这个类模板
    template<typename  T, typename  Ref, typename  Ptr>
    struct __list_iterator//迭代器
    {
    public:
         friend class  list<T>;//在模板类A里面声明另外一个模板类B作为友元类,需要在该模板类A前面声明(如果B有定义在A后面的需求)或者定义模板类B才行
        //原因就是编译器找类的时候是自下而上的。
        typedef list_node<T> Node;
        typedef __list_iterator<T, Ref, Ptr> self;
        //这里以建立一个模板类,里面实现基本的list迭代器操作。
        __list_iterator() 
        :tmp(nullptr)
        {

        }
        __list_iterator(Node* val)
        :tmp(val)
        {

        }
        Ref operator*()
        {
            return tmp->_data;
        }
        Ptr operator->()const
        {
            return &(tmp->_data);
        }
        self& operator++()
        {
            tmp = tmp->_next;
            return *this;
        }
        self operator++(int)//后置
        {
            self t_iterator = *this;
            tmp = tmp->_next;
            return t_iterator;
        }
        self& operator--()
        {
            tmp = tmp->_prev;
            return *this;
        }
        self operator--(int)//后置
        {
            self t_iterator = *this;
            tmp = tmp->_prev;
            return t_iterator ;
        }
        bool operator!=(const self& it_2)
        {
            return tmp != it_2.tmp;
        }
        bool operator==(const self & it_2)
        {
            return tmp == it_2.tmp;
        }
        private:
        Node* tmp;
    };
template <class T>
    class list
    {
        typedef list_node<T> Node;
        public:
            typedef __list_iterator<T, T&, T*> iterator;
		    typedef __list_iterator<T, const T&, const T*> const_iterator;  
            typedef __reverse_iterator<T, T&, T*> reverse_iterator;
		    typedef __reverse_iterator<T, const T&, const T*> const_reverse_iterator;

            iterator begin()
            {
                return _head->_next;//隐式类型转换
            }
            iterator end()
            {
                return _head;//隐式类型转换
            }
            const_iterator begin()const
            {
                return _head->_next;//隐式类型转换
            }
            const_iterator end()const
            {
                return _head;//隐式类型转换
            }

            reverse_iterator rbegin()
            {
                return _head->_prev;//隐式类型转换
            }
            reverse_iterator rend()
            {
                return _head;//隐式类型转换
            }
            const_reverse_iterator rbegin()const
            {
                return _head->_prev;//隐式类型转换
            }
            const_reverse_iterator rend()const
            {
                return _head;//隐式类型转换
            }   
            *list()
            {
                empty_list();
            }
        
            template <class InputIterator>
            list(InputIterator first, InputIterator last)
            {
                empty_list();
                insert(end(),first,last);
            }
            list(size_t n,const T& val = T())
            {
                empty_list();
                while(n--!=0)
                {
                    push_back(val);
                }
            }
            list(int n,const T& val = T())
            {
                empty_list();
                while(n--!=0)
                {
                    push_back(val);
                }
            }
            list(const list& val)
            {
                empty_list();
                insert(end(),val.begin(),val.end());
            }
            ~list()
            {
                clear();
                delete _head;
            }
            void swap(list & t)
            {
                Node* tt = t._head;
                t._head = _head;
                _head = tt;
            }
            void empty_list()
            {
                _head = new Node;
                _head->_next = _head;
                _head->_prev = _head;
            }
            list& operator=(const list& val)
            {
                clear();
                insert(end(),val.begin(),val.end());
                return *this;
            }
            void push_back(const T& val)
            {
                insert(end(),val);
            }
            void push_front(const T& val)
            {
                insert(begin(),val);
            }
            void pop_front()
            {
                erase(begin());
            }
            void pop_end()
            {
                erase(end()--);
            }
            iterator insert(iterator pos,const T& val = T())
            {
                Node* prev = pos.tmp->_prev;
                Node* cur = pos.tmp;
                Node* newnode = new Node;
                newnode ->_data = val;
                newnode->_next = cur;
                newnode->_prev = prev;
                prev->_next = newnode;
                cur->_prev = newnode;
                _size++;
                return newnode;
            }
            template <class InputIterator>
            void insert (iterator position, InputIterator first, InputIterator last)
            {
                while(first != last)
                {
                    position = insert(position,*first++);
                    position++;
                }
            }
            iterator erase(iterator pos)
            {
                Node* tmp = pos.tmp;
                Node *prev = tmp->_prev;
                Node *next = tmp->_next;
                delete tmp;
                next->_prev = prev;
                prev->_next = next;
                _size--;
                return next;
            }
            void clear()
            {
                iterator it = begin();
                while(it != end())
                {
                    it = erase(it);
                }
            }*
        private:
            Node* _head;
            size_t _size = 0;
    };

具体实现的代码已上传。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值