C++汎用プログラミングまとめ(一)

7093 ワード

目次:
  1.STLの組成
    2.ポインタの算術演算
    3.汎用find()の実現&汎用ポインタiteratorの役割
    4.一般的な汎用アルゴリズムの要約
    5.すべてのコンテナの汎用操作
    6.シーケンスコンテナvector,list,dequeの挿入と削除
vector iterators incompatibleエラー回避と原因分析
 1.STLの組成
(1)容器container:vectorlistsetmappair……
(2)汎用アルゴリズムgeneric algorithm:find()sort()replace()merge()......
2.ポインタの算術演算
    array[2]  ==  *(array+2)
arrayの最初の要素のアドレス1000の場合、array+2!=1002、「ポインタが指すタイプ」を考慮しなければならないからです
例:intが4 byte(32 bit,1マシンワード長)であればarray+2==1008
3.汎用find()の実現&汎用ポインタiteratorの役割
要求:1.適応タイプint,stringなど.2.適応array,vector
template
inline elemType* begin(const vector& vec)
{ return vec.empty() ? 0 : &vec[0]; }

template
const elemType* find(const elemType* first,  //      ,  const      
    const elemType *last,const elemType& value) 
{
    if(!first || !last)
        return 0;
    for(;first != last; ++first)
        if(*first == value)
            return first;
    return 0;
}
//  
int ia[8] = {1,1,2,3,5,8,13,21};
const int* pi=find(ia,ia+8,ia[3]);
//vector
find(begin(svec),end(svec),search_value)

注記:iteratorを使用すると、find()をvectorとlistの2つの異なるコンテナに適応できます.
iteratorは汎用ポインタとして、異なる容器間の違いを隠すために使用されます.
汎用アルゴリズムの実現の基礎
要求3:異なる容器に適応した汎用find()
template
IteratorType find(IteratorType first,IteratorType last,
    const elemType& value)
{
    for(;first != last;++first)
        if(*first == value)
            return first;
    return last;
}
int main()
{
    int ia[8] = {1,1,2,3,5,8,13,21};
    int *pi=find(ia,ia+8,5);
    if(pi != pi+8)
        cout< vec(ia,ia+8);
    vector::iterator iter =find(vec.begin(),vec.end(),22);
    if(iter != vec.end())
        cout<

4.一般的な汎用アルゴリズム(Essential付録B)
int ia[8] = {1,1,2,3,5,8,13,21};
int ia2[9] = {1,1,2,3,5,8,13,21,24};
list ilist(ia,ia+8)
以下、iaはilistに相当する.begin()、ia+8はilistに相当する.end()
「*」を付けると、再構築可能な演算タイプが表示されます.再構築方法は次のとおりです.
class Even
{
public:
    bool operator()(int val)
    { return !(val%2); }
};
ires = count_if(ia,ia+8,Even())
class Twiceover
{
public:
    bool operator()(int val1,int val2)
    { return val1==val2/2 ? true : false; }
}
iter=adjacent_find(ia,ia+8,Twiceover())
検索けんさく:iter
find(ia,ia+8,value)が見つかったら、その反復器に戻ります.そうでなければend()を返し、find_を添付します.end()
find_if(ia,ia+8,LessThanVal(val))が見つかると反復器に戻ります
*adjacent_find(ia,ia+8)は、隣接する重複要素の最初の要素のセットの最初の反復器を返します.
count(ilist.begin(),ilist.end,value)は、コンテナ内のvalueに等しい要素の数を返します.
*count_if(ia,ia+8,bind 2 nd(less(),10))は「<10」の要素個数を返す
*binary_Search(ia,ia+8,value)は「
find_first_of()一部の要素が初めて現れた場所を検索する
search()シーケンス1でシーケンス2を検索し、シーケンス2の先頭にある反復器を返す
ソート&順序整理:merge(ia,ia+8,ia 2,ia 2+9,result.begin()はソートされたシーケンスをマージし、resultpartial_と配置します.sort()ローカルソートpartition()ローカル合計random_shuffle(vec.begin(),vec.end()ランダム再配列reverse(ilist.begin(),ilist.end()逆要素順序rotate(ia,ia+3,ia+8)回転結果:{3,5,8,13,21,1,2}sort(ia,ia+8)小さいものから大きいものへ並べ替え
コピー、削除、置換:copy(ilist.begin()、ilist.end,listCopy.begin()コピーcopy_backward逆レプリケーションremove(vec.begin()vec.end(),0)要素は削除されますが*remove_は削除されませんif(vec.begin(),vec.end(),Even()は削除後の有効反復器end()replace(vec.begin(),vec.を返す.end()、oldval、newval)は、ある要素repace_に取って代わります.if(vec.begin(),vec.end()、bind 2 nd(less()、10)、new)は、swap()交換unique(vec.begin、vec.end()の代わりに重複要素を折り畳んで一意にする条件があり、removeと同様にfill(ia、ia+8、value)がvalueに変更され、fill_n(ia,n,value)n個の要素値のみをvalueとする
関係:*equal(ia,ia+7,ia 2)、等長部分要素が等しい場合はtrueを返し、ia 2の多くの要素はincludes(ia 2,ia 2+9,ia,ia+8)にかかわらずiaの要素がia 2にある場合はtrueを返し、iaとia 2がソートされたmismatch()max(ia[0],ia[1])は2つの要素の最大値max_を返します.Element(ia,ia+8)は、最大値の反復器distance(ia,iter)を返し、iterおよびiaのような2つの反復器の距離を返します.
数値:*accmulate(ia,ia+8,0)は要素の累積結果を返し、「0」は指定した初期値adjacent_difference(ia,ia+8,iresult.begin())隣接する要素の差額{0,1,2,3,5,8}->{0,1,0,1,2,3}は0位を保持し、その他:このビット-前のpartial_sum()                                                                                      *inner_product(ia,ia+8,ia 2,0)内積、対応乗算再加算
コレクション:
set_union(ia,ia+8,ia 2,ia 2+9,ia 3)を並べて{0,1,2,3}+{0,2,4,6}={0,1,2,3,4,6}
set_difference(ia,ia+8,ia 2,ia 2+9,ia 3)差集合,集合1はあるが,集合2木にある元素を抽出して並べ替えて集合3に入れる
.集合1と2は順番に並べておきます
より重要な汎用性
int ia[] = {0,1,0,2,0,3,0,4,0,5};
vector vec(ia,ia+10);
vec_iter = remove(vec.begin(),vec.end(),0)/0は削除する要素です
//remove()操作後、erase()操作前のvector内容:{1,2,3,4,5,3,0,4,0,5}
//保持する要素はすべて前にコピーされます.
vec.erase(vec_iter,vec.end());//erase()操作後のvector内容:1,2,3,4,5
//配列はサイズ変更しにくいのでremoveは適用されずremove_copy()
int ia2[5]
remove_copy(ia,ia+10,ia 2,0)/ia 2:1,2,3,4,5を得る
5.全ての容器の共通操作
equality==   inequality!=   assignment=   empty()size()
  • clear()
  • begin()end()は反復器
  • を返す
  • insert()挿入
  • erase()削除
  • 6.シーケンスコンテナvector,list,dequeの挿入と削除
    定義:
  • vectorivec(32)/サイズ32、デフォルトの各値は0で、ランダムアクセス
  • に適用されます.
  • listM slist(16,unassigned)/サイズ16、各文字に「unassigned」を割り当てると、削除操作が頻繁に挿入される
  • に適用されます.
    挿入削除:
  • 汎用:push_back(),pop_back()
  • listとdequeそしてpush_front(),pop_front()
  • 汎用:front()back()は、最前端または最後端の値
  • を返します.
    vectorの削除eraseとinsertの挿入vector iterators incompatibleエラーを避けるため、挿入削除後に値を割り当てる
    #include
    #include
    #include
    template 
    void DeleteVector(vector &data, T key)
    {
        //vector::iterator itr = data.begin();
        //while(itr != data.end())
        //{
        //    if(*itr == key){
        //        itr=data.erase(itr); //     itr
        //        return;
        //    }
        //    else
        //        ++itr;
        //}
        vector::iterator iter = find(data.begin(),data.end(),key);
        if(iter != data.end())
            iter=data.erase(iter);
    }
    template 
    void InsertVector(vector &data, T key)
    {
        vector::iterator itr = data.begin();
        while (itr != data.end())
        {
            if(*itr < key)
                itr=itr+1;
            else{
                itr=data.insert(itr,key); //    itr
                break;
            }
        }
        if(itr == data.end())
            data.push_back(key);
        return;
    }

    itrが挿入または削除後に値を付与していない場合、vector iterators incompatibleのエラーが発生する可能性があります.
    原因を分析する
  • 挿入後にitrを変更するなければ、itrとdataを下で比較する.end()では、エラーが発生します.
  • の問題はinsertの後に現れ、vectorのチェーンテーブルが変更され、新しく挿入された要素はiteratorが参照したアドレスではありません.
  • 正しい方法は、insert()が返す挿入要素のiteratorをitrに割り当てることである.
  • 同理erase()にも同様の問題があり、eraseの1つの要素の後、後続の要素はiteratorが参照する位置に必ずしも移動しない.

  • このエラーの原因は次のとおりです.
  • 空のVectorの問題.空のvectorを参照するbegin反復器は許可されません.vectorは空なので、自然に最初のプロジェクトはありません.vector iterators incompatibleも発生します.vector.clear()後、vectorは使用できません.begin()
  • vc 2005は反復器のマッチングに非常に厳格であり、通常、このエラーは、2つの異なる反復器が同じvectorを操作しているため、または反復器がvectorを遍歴している間にvectorのチェーンテーブルが変化したため、vectorが遍歴中、別の位置push_back()要素の場合、反復器が無効になり、エラーが発生します.臨界領域反発アクセスを使用できます.