string的sso实现

sso的全称是Small String Optimization,小字符串优化。

struct _Alloc_hider : allocator_type // TODO check __is_final
      {
	_Alloc_hider(pointer __dat, const _Alloc& __a = _Alloc())
	: allocator_type(__a), _M_p(__dat) { }

	pointer _M_p; 
      };

_M_p就是真正的数据的指针。

_Alloc_hider	_M_dataplus;
      size_type		_M_string_length;

      enum { _S_local_capacity = 15 / sizeof(_CharT) };

      union
      {
	_CharT           _M_local_buf[_S_local_capacity + 1];
	size_type        _M_allocated_capacity;
      };

_M_string_length是数据的长度,_M_local_buf就是预分配的小块内存,如果_CharT是char类型的话,_S_local_capacity=15,_M_local_buf的大小就是16字节,_M_allocated_capacity是当数据的大小大于预分配的小块内存的时候分配的内存大小。如果小于预分配的小块内存的大小就使用_M_local_buf,如果大于就分配新的内存,这时用到_M_allocated_capacity,它们不会并存,所以可以放到一个union里面。

默认构造函数:

basic_string() _GLIBCXX_NOEXCEPT
      : _M_dataplus(_M_local_data())
      { _M_set_length(0); }
默认构造函数把小块内存的地址赋给了数据指针,并且将_M_string_length设为0.


basic_string(const basic_string& __str)
      : _M_dataplus(_M_local_data(), __str._M_get_allocator()) 
      { _M_construct(__str._M_data(), __str._M_data() + __str.length()); }
拷贝构造函数把活都转给了_M_construct:
template<typename _InIterator>
        void
        _M_construct(_InIterator __beg, _InIterator __end)
	{
	  typedef typename std::__is_integer<_InIterator>::__type _Integral;
	  _M_construct_aux(__beg, __end, _Integral());
        }

_M_construct又把活转给了_M_construct_aux:

template<typename _InIterator>
        void
        _M_construct_aux(_InIterator __beg, _InIterator __end,
			 std::__false_type)
	{
          typedef typename iterator_traits<_InIterator>::iterator_category _Tag;
          _M_construct(__beg, __end, _Tag());
	}

因为指针不是integer,所以是__false_type.

由前面的博文我们知道指针的iterator_category是random_access_iterator_tag,派生自input_iterator_tag,于是转到了下面的函数:

template<typename _CharT, typename _Traits, typename _Alloc>
    template<typename _InIterator>
      void
      basic_string<_CharT, _Traits, _Alloc>::
      _M_construct(_InIterator __beg, _InIterator __end,
		   std::input_iterator_tag)
      {
	size_type __len = 0;
	size_type __capacity = size_type(_S_local_capacity);//15

	while (__beg != __end && __len < __capacity)
	  {
	    _M_data()[__len++] = *__beg;
	    ++__beg;
	  }
	//__beg==__end 或者__len==__capacity(即申请的栈内存已用完)
	__try
	  {
	    while (__beg != __end)
	      {
		if (__len == __capacity)//申请的栈内存已用完
		  {
		    // Allocate more space.
		    __capacity = __len + 1;
		    pointer __another = _M_create(__capacity, __len);//分配更多的内存,可能会失败
		    this->_S_copy(__another, _M_data(), __len);//将原来的数据拷贝到新的内存
		    _M_dispose();//如果以前是new出来的内存,则释放该内存;如果以前是缓存,则不用释放
		    _M_data(__another);//新数据的指针
		    _M_capacity(__capacity);//新分配的内存的大小
		  }
		_M_data()[__len++] = *__beg;
		++__beg;
	      }
	  }
	__catch(...)
	  {
	    _M_dispose();//如果以前是new出来的内存,则释放该内存
	    __throw_exception_again;
	  }

	_M_set_length(__len);
      }

赋值操作符:

basic_string&
      operator=(const basic_string& __str)
      { return this->assign(__str); }

把活转给了assign:

basic_string&
      assign(const basic_string& __str)
      {
	this->_M_assign(__str);
	return *this;
      }

又转给了_M_assign:

template<typename _CharT, typename _Traits, typename _Alloc>
    void
    basic_string<_CharT, _Traits, _Alloc>::
    _M_assign(const basic_string& __str)
    {
      if (this != &__str)
	{
	  const size_type __rsize = __str.length();
	  const size_type __capacity = capacity();

	  if (__rsize > __capacity)
	    {
	      size_type __new_capacity = __rsize;
	      pointer __tmp = _M_create(__new_capacity, __capacity);
	      _M_dispose();
	      _M_data(__tmp);
	      _M_capacity(__new_capacity);
	    }

	  if (__rsize)
	    this->_S_copy(_M_data(), __str._M_data(), __rsize);

	  _M_set_length(__rsize);
	}
    }

析构函数:

~basic_string(){ _M_dispose(); }
void _M_dispose()
      {
    if (!_M_is_local())
      _M_destroy(_M_allocated_capacity);
      }

      void
      _M_destroy(size_type __size) throw()
      { _Alloc_traits::deallocate(_M_get_allocator(), _M_data(), __size + 1); }
 


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值