STLソースのメモ2 - 特徴
簡単な紹介
STLソースで、単語が広く、この抽出を発現するために使用される方法の説明の形質に使用されます。対応するイテレータイテレータイテレータの特性、クラス型のタイプに対応した特性、ポインタのような特徴のポインタへのポインタを含むいくつかの一般的な使用でのSTLの特性、。そして、その核となるアイデアは、さまざまな操作やアルゴリズムの一般化などに通じその後、私たちすることができます機構特徴、明確に定義されたルールのいくつかの種類、このルールに従って与えられた定義に対応するだけの書き込みコードを考えることです。
イテレータの特徴
ただ、説明の上、完全に、STLのソースコード内の形質の役割を理解する最も広く使用されているコンテナイテレータ関連イテレータ特徴があるかもしれません。いくつかのアルゴリズムまたは関数内STLイテレータに渡されている理由も不思議に思うかもしれSTLを使用した場合の前に、あなたが正しく実行することができますが、イテレータ各コンテナの対応がまったく同じではありませんが、自分の特性を持っています、ので、どのように彼らはそれを達成したのですか?
たとえば、私たちは高度なgcc2.95のSTLのソースコード()関数を参照してください
template <class _InputIterator, class _Distance>
inline void advance(_InputIterator& __i, _Distance __n) {
__advance(__i, __n, iterator_category(__i));
}
__advance()部分特殊のいくつかのバージョンがあります。
template <class _InputIter, class _Distance>
inline void __advance(_InputIter& __i, _Distance __n, input_iterator_tag) {
while (__n--) ++__i;
}
#if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM != _MIPS_SIM_ABI32)
#pragma set woff 1183
#endif
template <class _BidirectionalIterator, class _Distance>
inline void __advance(_BidirectionalIterator& __i, _Distance __n,
bidirectional_iterator_tag) {
if (__n >= 0)
while (__n--) ++__i;
else
while (__n++) --__i;
}
#if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM != _MIPS_SIM_ABI32)
#pragma reset woff 1183
#endif
template <class _RandomAccessIterator, class _Distance>
inline void __advance(_RandomAccessIterator& __i, _Distance __n,
random_access_iterator_tag) {
__i += __n;
}
見ることができ、コールadvance
と呼ばれる時間、__advance()
及び第三引数に渡されたが、それは経由でiterator_category()
抽出されたイテレータ型、その後、種類に応じて、部分特殊の異なるバージョンを入力します__advance()
。でstl_iterator.h
ドキュメント内の値iterator_categoryに基づいてオブジェクトのコンストラクタを返すために)(iterator_category見ることができます。
template <class _Iter>
inline typename iterator_traits<_Iter>::iterator_category
iterator_category(const _Iter& __i) { return __iterator_category(__i); }
template <class _Iter>
inline typename iterator_traits<_Iter>::iterator_category
__iterator_category(const _Iter&)
{
typedef typename iterator_traits<_Iter>::iterator_category _Category;
return _Category();
}
その結果iterator_categoryは、機能部分特殊最終版が呼び出されます決定定義されたときに、全体のプロセスのイテレータ特徴は、イテレータの定義によれば、実際には、出てきた、と私たちは、コンテナを定義する必要があれば、対応するイテレータを聞かせてSTL反復子が種々の機能に使用することができ、ルールは、認識のこの種類に応じて、明確に定義された反復子である必要があります。識別一般的に使用されるタイプは以下のとおりであります:
template <class _Iterator>
struct iterator_traits {
typedef typename _Iterator::iterator_category iterator_category; //迭代器类型(可随机访问的迭代器、单向迭代器、双向迭代器等)
typedef typename _Iterator::value_type value_type; //容器类型(类类型)
typedef typename _Iterator::difference_type difference_type; //标识迭代器距离
typedef typename _Iterator::pointer pointer; //指针
typedef typename _Iterator::reference reference; //引用
};
タイプの特徴
同じタイプの特性も、一般的な機能を処理するための技術である、抽出の必要性は密接に農産物のクラスまたはタイプに関連ものです。興味クラスのコンストラクタのほかのいくつかのタイプの特徴は、コンストラクタ、デストラクタをコピーし、機能割り当ての条件のようにすることにより、より効率的な共通のコードを生成し、重要です。
template <class _Tp>
struct __type_traits {
typedef __true_type this_dummy_member_must_be_first;
typedef __false_type has_trivial_default_constructor; //不重要的默认构造函数
typedef __false_type has_trivial_copy_constructor; //不重要的拷贝构造函数
typedef __false_type has_trivial_assignment_operator; //不重要的赋值函数
typedef __false_type has_trivial_destructor; //不重要的析构函数
typedef __false_type is_POD_type; //plain old data 普通旧数据
};
これは、ソースコードのGCC 2.95バージョンであり、そのコピー()関数を観察しました。効率コピー()関数は、様々なタイプのために見ることができるので、容器内部の非常に重要な機能は、全体のほぼコピーし、それはまた、コンテナの効率に大きな影響ださは、非常に詳細なプロセスを作りました:
template <class _InputIter, class _OutputIter>
inline _OutputIter copy(_InputIter __first, _InputIter __last,
_OutputIter __result) {
typedef typename iterator_traits<_InputIter>::value_type _Tp;
typedef typename __type_traits<_Tp>::has_trivial_assignment_operator
_Trivial;
return __copy_dispatch<_InputIter, _OutputIter, _Trivial>
::copy(__first, __last, __result);
}
inline char* copy(const char* __first, const char* __last, char* __result) {
memmove(__result, __first, __last - __first);
return __result + (__last - __first);
}
inline wchar_t* copy(const wchar_t* __first, const wchar_t* __last,
wchar_t* __result) {
memmove(__result, __first, sizeof(wchar_t) * (__last - __first));
return __result + (__last - __first);
}
上記のコードは、最初の反復バージョンに加えて、他の2つの文字列が直接MEMMOVE操作され、三つのカテゴリー、反復バージョン、およびバージョン文字列はwchar_t * CHAR *バージョンに分割し、非常に高い効率です。それでは実現のイテレータバージョンを見下ろします。
template <class _InputIter, class _OutputIter, class _BoolType>
struct __copy_dispatch {
static _OutputIter copy(_InputIter __first, _InputIter __last,
_OutputIter __result) {
typedef typename iterator_traits<_InputIter>::iterator_category _Category;
typedef typename iterator_traits<_InputIter>::difference_type _Distance;
return __copy(__first, __last, __result, _Category(), (_Distance*) 0);
}
};
template <class _Tp>
struct __copy_dispatch<_Tp*, _Tp*, __true_type>
{
static _Tp* copy(const _Tp* __first, const _Tp* __last, _Tp* __result) {
return __copy_trivial(__first, __last, __result);
}
};
template <class _Tp>
struct __copy_dispatch<const _Tp*, _Tp*, __true_type>
{
static _Tp* copy(const _Tp* __first, const _Tp* __last, _Tp* __result) {
return __copy_trivial(__first, __last, __result);
}
};
type_traits分析は、それが部分的な特殊ポインタまたはconstのポインタになりますhas_trivial_assignment_operatorクラスは、__true_typeで見つかった後にそれがあるかどうかは、分離__copy_dispatch後、イテレータのバージョンのために見ることができます。この場合、ダイレクトコール__copy_trivialを達成することとなっているコピーは、内部実装は迅速MEMMOVEの使用です。ソースとして、次のとおりです。
template <class _Tp>
inline _Tp*
__copy_trivial(const _Tp* __first, const _Tp* __last, _Tp* __result) {
memmove(__result, __first, sizeof(_Tp) * (__last - __first));
return __result + (__last - __first);
}
特別な割り当て関数は、再度単離し、一般的なイテレータとランダムイテレータがある場合と、両者のイテレータの差はrandomAccessIterが最も効率的に高める一層、サイクルの前のサイクルの正確数を知る必要があるかもしれないことです。
template <class _InputIter, class _OutputIter, class _Distance>
inline _OutputIter __copy(_InputIter __first, _InputIter __last,
_OutputIter __result,
input_iterator_tag, _Distance*)
{
for ( ; __first != __last; ++__result, ++__first)
*__result = *__first;
return __result;
}
template <class _RandomAccessIter, class _OutputIter, class _Distance>
inline _OutputIter
__copy(_RandomAccessIter __first, _RandomAccessIter __last,
_OutputIter __result, random_access_iterator_tag, _Distance*)
{
for (_Distance __n = __last - __first; __n > 0; --__n) {
*__result = *__first;
++__first;
++__result;
}
return __result;
}
言葉の後
上記の二つのソースコードから、私たちは、実際に形質は中間の変換として機能していることがわかります。彼らは、パラメータのどの特定のタイプを知っているので、一般化後のSTLの多くの機能については、特色を向上メカニズム場合、抽象後にこれらの一般化の機能をうまく利用することができます。そして、いくつかのコンテナや独自のクラスを記述する場合は、限り対応する識別タイプが定義されているとして、それも一緒に使用するSTLに統合することができます。