###学習《C++Primer》-3
6979 ワード
クリックしてEvernoteのテキストを表示 .
Part 3:STL汎用アルゴリズム(第10章)
一、アルゴリズムは永遠に容器の操作を実行しない
アルゴリズム自体はコンテナの操作を実行せず、反復器でのみ実行され、反復器の操作を実行し、反復器を使用してアルゴリズムをより汎用化します.アルゴリズムのプログラミング仮定:アルゴリズムは決して下層容器の大きさを変えない.アルゴリズムは、要素の値を変更したり、要素を移動したりすることができますが、直接追加したり削除したりすることはありません.
二、読み取り専用アルゴリズム
三、容器要素を書くアルゴリズム
四、容器要素を並べ替えるアルゴリズム
五、lambda式
$$$lambda$$式は関数と同様にアルゴリズム呼び出しに渡すことができます.一般的な形式は次のとおりです.
パラメータリストと戻りタイプは無視できますが、キャプチャリストと関数体は常に含まなければなりません.
次に、この
取得リストを使用して現在のローカル変数を取得し、
六、変数の修正がlambda式に与える影響
取得のタイプ:1.値の取得;2.参照取得;3.暗黙的なキャプチャ.≪値の取得|Value Capture|emdw≫:取得された値はlambdaの作成時にコピーされ、取得されたローカル変数の値を変更してもlambdaの値には影響しません.値取得:参照取得は値取得とは逆に、変更した値がlambda式の内部に作用します.
暗黙的なキャプチャ:コンパイラに
七、lambda式で変数値を修正する
一般的にlambda式では、値取得でコピーされた変数の値は変更されません.lambda式で値を変更する場合は、式をmutableとして宣言する必要があります.
リファレンスキャプチャが変更できるかどうかは、リファレンスが
八、lambda式の戻りタイプ
条件演算子のタイプに基づいて推定できるため、いくつかの式では戻りタイプを指定する必要はありません.lambda式の戻りタイプを定義する必要がある場合は、末尾の戻りタイプを使用する必要があります.
九、パラメータバインド
パラメータ:
パラメータの再配置:
十、反復器を挿入する
挿入反復器に値を割り当てるのはコンテナに書き込むのと同じで、挿入関数が自動的に呼び出されます.
十一、フロー反復器
十二、逆反復器
逆反復器は、最後に現れる要素を検索する際に非常に有効ですが、逆反復器を直接使用して出力すると、順序が逆になり、反復器の
十三、アルゴリズムパラメータモード
一般的なアルゴリズムには基本的なパラメータ形式があり,これらのモードを理解し,アルゴリズムの操作にもっと集中することができる.一般的には、次の4つの形式があります.
十四、アルゴリズム命名規範いくつかのアルゴリズムは、述語 をリロードするように伝達する. _ifバージョンのアルゴリズム コピー要素バージョンと非コピーバージョンを区別する
#@author: gr
#@date: 2014-10-04
#@email: [email protected]
Part 3:STL汎用アルゴリズム(第10章)
一、アルゴリズムは永遠に容器の操作を実行しない
アルゴリズム自体はコンテナの操作を実行せず、反復器でのみ実行され、反復器の操作を実行し、反復器を使用してアルゴリズムをより汎用化します.アルゴリズムのプログラミング仮定:アルゴリズムは決して下層容器の大きさを変えない.アルゴリズムは、要素の値を変更したり、要素を移動したりすることができますが、直接追加したり削除したりすることはありません.
inserter
の反復器もあり、容器に要素を追加することができます.二、読み取り専用アルゴリズム
accumulate
は、加算動作を行い、数値加算を行ってもよいし、文字列加算(接続)を行ってもよい.accumulate(c.cbegin(), c.cend(), string(""));
equal
は、2つの容器の要素が一致しているかどうかを比較し、最初の2つは容器の範囲を表し、3番目は2番目の容器の最初の位置を表す.2番目のシーケンスが少なくとも1番目のシーケンスと同じ長さであることを保証します.equal(c1.cbegin(), c1.cend(), c2.cbegin());
三、容器要素を書くアルゴリズム
fill
とfill_n
は容器の大きさを変えないので、十分なスペースが確保されています.vector<int> vec(10);
fill(vec.begin(), vec.end(), 0); //fill(begin, end, val);
fill_n(vec.begin(), vec.size(), 0); //fill_n(pos, n, val);
vector<int> vec2;
fill_n(vec2.begin(), 10, 0); // ,vec2 , 10
back_inserter
は挿入反復器であり、この反復器によって付与されると、push_back
関数が自動的に呼び出されます.vector<int> vec;
auto it = back_inserter(vec);
// , push_back
*it = 42;
fill_n(back_inserter(vec), 10, 1);
copy
は、エレメントを宛先に書き込みます.copy(vec1.cbegin(), vec2.cend(), back_inserter(vec2));
replace
は、要素値を置き換えます.// 0 42
replace(vec.begin(), vec.end(), 0, 42);
replace_copy
は、第3の反復器を受け入れ、調整後のシーケンスの保存位置を示す.replace_copy(vec.cbegin(), vec.cend(), back_inserter(vec2), 0, 42);
四、容器要素を並べ替えるアルゴリズム
unique
は、重複する要素を本当に削除していません.重複する要素を最後に並べます.end()
メンバー関数が返す反復器の位置は変わりません.erase
を呼び出して削除した後、重複する要素を本当に削除します.vector<string> words = {"fox", "the", "red", "jump"}
//
sort(words.begin(), words.end());
// ,
auto end_unique = unique(words.begin(), words.end());
//
words.erase(end_unique, words.end());
五、lambda式
$$$lambda$$式は関数と同様にアルゴリズム呼び出しに渡すことができます.一般的な形式は次のとおりです.
[capture list] (parameter list) -> return type { function body }
パラメータリストと戻りタイプは無視できますが、キャプチャリストと関数体は常に含まなければなりません.
auto f = [] {return 42;} ;
//
[](const string& a, const string& b){ return a.size() < b.size(); }
次に、この
lambda
式を用いてアルゴリズムに伝達してソートする.stable_sort(words.begin(), words.end(),
[](const string& a, const string& b)
{ return a.size() < b.size(); } );
取得リストを使用して現在のローカル変数を取得し、
lambda
式で直接使用できます.[sz](const string& a){
return a.size() >= sz;
};
六、変数の修正がlambda式に与える影響
取得のタイプ:1.値の取得;2.参照取得;3.暗黙的なキャプチャ.≪値の取得|Value Capture|emdw≫:取得された値はlambdaの作成時にコピーされ、取得されたローカル変数の値を変更してもlambdaの値には影響しません.値取得:参照取得は値取得とは逆に、変更した値がlambda式の内部に作用します.
size_t v1 =42;
auto f1 = [v1]{return v1;} //
auto f2 = [&v1]{return v1;} //
v1 = 0;
auto j = f1(); // , 42
auto k = f2(); // , 0
暗黙的なキャプチャ:コンパイラに
lambda
式のコードに基づいて、どの変数を使用する必要があるかを推定させます.暗黙的なキャプチャであることを示すために、キャプチャリストに&または=を追加します.&参照取得を表します.=値取得を表します.wc = find_if(words.begin(), words.end(),
[=](const string& s){return s.size > sz;} );
七、lambda式で変数値を修正する
一般的にlambda式では、値取得でコピーされた変数の値は変更されません.lambda式で値を変更する場合は、式をmutableとして宣言する必要があります.
size_t v1 = 42;
auto f = [v1] () mutable {return ++v1;};
v1 = 0;
auto j = f(); //j 43
リファレンスキャプチャが変更できるかどうかは、リファレンスが
const
タイプであるかどうかによって異なります.size_t v1 = 42;
auto f = [&v1]{return ++v1;}; //v1 const
v1 = 0;
auto j = f2(); //j 1
八、lambda式の戻りタイプ
条件演算子のタイプに基づいて推定できるため、いくつかの式では戻りタイプを指定する必要はありません.lambda式の戻りタイプを定義する必要がある場合は、末尾の戻りタイプを使用する必要があります.
transform(vi.begin(), vi.end(), vi.begin(),
[](int i)-> int // int
{ if (i < 0) return -i; else return i; });
九、パラメータバインド
bind
の一般的な形式:auto newCallable = bind(callable, arg_list);
arg_list
のパラメータには、次のような形が含まれる場合があります.nの名前、nは整数で、これらのパラメータは“ポイント記号”で、いくつかのパラメータを表します:1は第1のパラメータを表して、2は第2のパラメータを表します.find_if(words.begin(), words.end(),
bind(check_size, _1, sz)); // sz
パラメータ:
auto g = bind(f, a, b, _2, c, _1); //g
g(X, Y); // g(X,Y) f(a, b, Y, c, X);
パラメータの再配置:
auto g = bind(f, _2, _1);
g(X, Y); // g(X,Y) f(Y, X),
十、反復器を挿入する
挿入反復器に値を割り当てるのはコンテナに書き込むのと同じで、挿入関数が自動的に呼び出されます.
inserter
、back_inserter
、front_inserter
もすべて反復器で、これらの名前は元の反復器の別名で、元の名前は長すぎますo_0!
.vector<int> vi = {1, 2, 3};
auto it = back_inserter(vi); //
*it = 4; //vi {1, 2, 3, 4}
十一、フロー反復器
`iostream` , IO ,`istream_iterator`,`ostream_iterator`。
istream_iterator<int> in(cin), eof;
int sum = accumulate(in, eof, 0);
ostream_iterator<int> out_iter(cout, "
"); //
*out_iter = sum;
十二、逆反復器
逆反復器は、最後に現れる要素を検索する際に非常に有効ですが、逆反復器を直接使用して出力すると、順序が逆になり、反復器の
base()
メンバー関数によって正常な反復器に変えることができます.auto rcomma = find(line.crbegin(), line.crend(), ','); //
cout << string(line.crbegin(), recomma) << endl; // ,
cout << string(rcomma.base(), line.cend()) << endl; // base()
十三、アルゴリズムパラメータモード
一般的なアルゴリズムには基本的なパラメータ形式があり,これらのモードを理解し,アルゴリズムの操作にもっと集中することができる.一般的には、次の4つの形式があります.
alg(begin, end, args);
alg(begin, end, dest, args);
alg(begin, end, begin2, args);
alg(begin, end, begin2, end2, args);
十四、アルゴリズム命名規範
//unique
unique(begin, end);
unique(begin, end, comp); // , < ==
// ,
find(c.begin(), c.end(), val);
find_if(c.begin(), c.end(), condi); // condition
reverse(begin, end); //
reverse_copy(begin, end, dst); // dst, inserter