string(模拟实现与深拷贝)

深拷贝与浅拷贝

浅拷贝:

也称位拷贝,编译器只是将对象中的值拷贝过来。如果对象中管理资源,最后就会导致多个对象共享同一份资源,当一个对象销毁时就会将该资源释放掉,而此时另一些对象不知道该资源已经被释放,以为还有效,所以当继续对资源进项操作时,就会发生发生了访问违规

就像一个家庭中有两个孩子,但父母只买了一份玩具,两个孩子愿意一块玩,则万事大吉,万一不想分享就你争我夺,玩具损坏。
可以采用深拷贝解决浅拷贝问题,即: 每个对象都有一份独立的资源,不要和其他对象共享 。父母给每个孩子都买一份玩具,各自玩各自的就不会有问题了

深拷贝

如果一个类中涉及到资源的管理,其拷贝构造函数、赋值运算符重载以及析构函数必须要显式给出。一般情况都是按照深拷贝方式提供。
(下图来源于网图)

 

写时拷贝(了解)

写时拷贝就是一种拖延症,是在浅拷贝的基础之上增加了引用计数的方式来实现的。
引用计数:用来记录资源使用者的个数。在构造时,将资源的计数给成 1 ,每增加一个对象使用该资源,就给计数增加1 ,当某个对象被销毁时,先给该计数减 1 ,然后再检查是否需要释放资源,如果计数为 1 ,说明该对象时资源的最后一个使用者,将该资源释放;否则就不能释放,因为还有其他对象在使用该资源。

模拟实现

准备

namespace frog

{

  class string

  {

  public:

    typedef char* iterator;

  public:

    string(const char* str = "");

    string(const string& s);

    string& operator=(const string &s);

    ~string();

    //

    // iterator

    iterator begin();

    iterator end();

    /

    // modify

    void push_back(char c);

    string& operator+=(char c);

    void append(const char* str);

    string& operator+=(const char* str);

    void clear();

    void swap(string& s);

    const char* c_str()const;

    /

    // capacity

    size_t size()const

    size_t capacity()const

    bool empty()const

    void resize(size_t n, char c = '\0');

    void reserve(size_t n);

    /

    // access

    char& operator[](size_t index);

    const char& operator[](size_t index)const;

    /

    //relational operators

    bool operator<(const string& s);

    bool operator<=(const string& s);

    bool operator>(const string& s);

    bool operator>=(const string& s);

    bool operator==(const string& s);

    bool operator!=(const string& s);

    // 返回c在string中第一次出现的位置

    size_t find (char c, size_t pos = 0) const;

    // 返回子串s在string中第一次出现的位置

    size_t find (const char* s, size_t pos = 0) const;

    // 在pos位置上插入字符c/字符串str,并返回该字符的位置

    string& insert(size_t pos, char c);

    string& insert(size_t pos, const char* str);

     

    // 删除pos位置上的元素,并返回该元素的下一个位置

    string& erase(size_t pos, size_t len);

  private:

    char* _str;

    size_t _capacity;

    size_t _size;

  }

};

完整代码 

#pragma once
#include<iostream>
#include<string>
#include<assert.h>
namespace bit

{

    class string
    {

    public:

        typedef char* iterator;
		typedef char* iterator;
		typedef const char* const_iterator;


    public:

        string(const char* str = "")
            :_size(strlen(str))
            , _capacity(_size)
        {
            _str = new char[_capacity + 1];
            strcpy(_str, str);
        }

        string(const string& s)
        {
        	_str = new char[s._capacity+1];
        	strcpy(_str, s._str);
        	_size = s._size;
        	_capacity = s._capacity;
        }
		iterator begin()
		{
			return _str;
		}

		iterator end()
		{
			return _str + _size;
		}

		const_iterator begin() const
		{
			return _str;
		}

		const_iterator end() const
		{
			return _str + _size;
		}


        string& operator=(const string& s)
        {
            if (this != &s)
            {
                char* tmp = new char[s._capacity + 1];
                strcpy(tmp, s._str);

                delete[] _str;
                _str = tmp;
                _size = s._size;
                _capacity = s._capacity;
            }
        }

            ~string()
            {
                delete[] _str;
                _str = nullptr;
                _size = _capacity = 0;
            }
			void swap(string& s)
			{
				std::swap(_str, s._str);
				std::swap(_size, s._size);
				std::swap(_capacity, s._capacity);
			}

			
			
			
			string& operator=(string tmp)
			{
				swap(tmp);

				return *this;
			}

			

			char& operator[](size_t pos)
			{
				assert(pos < _size);

				return _str[pos];
			}

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

				return _str[pos];
			}

			size_t capacity() const
			{
				return _capacity;
			}

			size_t size() const
			{
				return _size;
			}

			const char* c_str() const
			{
				return _str;
			}

			void reserve(size_t n)
			{
				if (n > _capacity)
				{
					char* tmp = new char[n + 1];
					strcpy(tmp, _str);
					delete[] _str;
					_str = tmp;

					_capacity = n;
				}
			}

			void resize(size_t n, char ch = '\0')
			{
				if (n <= _size)
				{
					_str[n] = '\0';
					_size = n;
				}
				else
				{
					reserve(n);
					while (_size < n)
					{
						_str[_size] = ch;
						++_size;
					}

					_str[_size] = '\0';
				}
			}

			size_t find(char ch, size_t pos = 0)
			{
				for (size_t i = pos; i < _size; i++)
				{
					if (_str[i] == ch)
					{
						return i;
					}
				}

				return npos;
			}

			size_t find(const char* sub, size_t pos = 0)
			{
				const char* p = strstr(_str + pos, sub);
				if (p)
				{
					return p - _str;
				}
				else
				{
					return npos;
				}
			}

			string substr(size_t pos, size_t len = npos)
			{
				string s;
				size_t end = pos + len;
				if (len == npos || pos + len >= _size) 
				{
					len = _size - pos;
					end = _size;
				}

				s.reserve(len);
				for (size_t i = pos; i < end; i++)
				{
					s += _str[i];
				}

				return s;
			}

			void push_back(char ch)
			{
				if (_size == _capacity)
				{
					reserve(_capacity == 0 ? 4 : _capacity * 2);
				}

				_str[_size] = ch;
				++_size;
				_str[_size] = '\0';
			}

			void append(const char* str)
			{
				size_t len = strlen(str);
				if (_size + len > _capacity)
				{
					reserve(_size + len);
				}

				strcpy(_str + _size, str);
				_size += len;
			}

			string& operator+=(char ch)
			{
				push_back(ch);
				return *this;
			}

			string& operator+=(const char* str)
			{
				append(str);
				return *this;
			}

			
			void insert(size_t pos, char ch)
			{
				assert(pos <= _size);
				if (_size == _capacity)
				{
					reserve(_capacity == 0 ? 4 : _capacity * 2);
				}

				// 17:17
				size_t end = _size + 1;
				while (end > pos)
				{
					_str[end] = _str[end - 1];
					--end;
				}

				_str[pos] = ch;
				_size++;
			}

			void insert(size_t pos, const char* str)
			{
				assert(pos <= _size);

				size_t len = strlen(str);
				if (_size + len > _capacity)
				{
					reserve(_size + len);
				}

				// 挪动数据
				int end = _size;
				while (end >= (int)pos)
				{
					_str[end + len] = _str[end];
					--end;
				}

				strncpy(_str + pos, str, len);
				_size += len;
			}

			void erase(size_t pos, size_t len = npos)
			{
				assert(pos < _size);

				if (len == npos || pos + len >= _size)
				{
					_str[pos] = '\0';
					_size = pos;
				}
				else
				{
					size_t begin = pos + len;
					while (begin <= _size)
					{
						_str[begin - len] = _str[begin];
						++begin;
					}
					_size -= len;
				}
			}

			bool operator<(const string& s) const
			{
				return strcmp(_str, s._str) < 0;
			}

			bool operator==(const string& s) const
			{
				return strcmp(_str, s._str) == 0;
			}

			bool operator<=(const string& s) const
			{
				return *this < s || *this == s;
			}

			bool operator>(const string& s) const
			{
				return !(*this <= s);
			}

			bool operator>=(const string& s) const
			{
				return !(*this < s);
			}

			bool operator!=(const string& s) const
			{
				return !(*this == s);
			}

			void clear()
			{
				_str[0] = '\0';
				_size = 0;
			}
	private:
		char* _str;
		size_t _size;
		size_t _capacity;

		
	public:
		const static size_t npos;
	};

	const size_t string::npos = -1;

	

}

	

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

IT战斗蛙

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值