stringのsso実装
4651 ワード
ssoのフルネームはSmall String Optimization,小文字列最適化である.
_M_pは本当のデータのポインタです.
_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の中に置くことができます.
デフォルトのコンストラクタ:
_M_constructはまた仕事を変えたM_construct_aux:
ポインタはintegerではないので_false_type.
前のブログでポインタのiteratorを知っています.categoryはrandom_access_iterator_tag,派生input_iterator_tagは、次の関数に移動しました.
割り当てオペレータ:
仕事をassignに回した.
また_に転送しましたM_assign:
構造関数:
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
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
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
template
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
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); }