一、for_each
機能の説明:
- トラバーサルコンテナを実装する
関数プロトタイプ:
-
for_each(iterator beg, iterator end, _func);
//トラバーサルアルゴリズムはコンテナ要素をトラバースします
// begがイテレータを開始します
//終了はイテレータを終了します
// _ func関数または関数オブジェクト
for_eachのソースコードを分析する:
// FUNCTION TEMPLATE for_each
template <class _InIt, class _Fn>
_CONSTEXPR20 _Fn for_each(_InIt _First, _InIt _Last, _Fn _Func) { // perform function for each element [_First, _Last)
_Adl_verify_range(_First, _Last);
auto _UFirst = _Get_unwrapped(_First);
const auto _ULast = _Get_unwrapped(_Last);
for (; _UFirst != _ULast; ++_UFirst) {
_Func(*_UFirst);
}
return _Func;
}
ここで、最初のパラメーターはコンテナーのヘッドイテレーター、2番目のパラメーターはテールイテレーター、3番目のパラメーターは関数を渡すことです。
ここでは関数名が渡されることに注意してください。
関数名は何ですか?関数名は、実際には関数のアドレスです。
言い換えれば、次のように書くことができます。
vector<int> v;
v.push_back(1);
v.push_back(0);
v.push_back(1);
v.push_back(0);
v.push_back(1);
void(*p)(int) = print01;
(*p)(5);
for_each(v.begin(), v.end(), p);
関数ポインタpを使用して、print01関数のアドレスを格納します。
次に、ポインタをfor_eachに置くと、それも機能します。
引き続きソースコードを確認してください。
次に、イテレータの移動が行われ、各移動は関数ポインタを逆参照して関数呼び出しを行います。
呼び出しのパラメーターは次のとおりです。イテレーターが指す要素。
例:
#include <algorithm>
#include <vector>
//普通函数
void print01(int val)
{
cout << val << " ";
}
//函数对象
class print02
{
public:
void operator()(int val)
{
cout << val << " ";
}
};
//for_each算法基本用法
void test01() {
vector<int> v;
for (int i = 0; i < 10; i++)
{
v.push_back(i);
}
//遍历算法
for_each(v.begin(), v.end(), print01);
cout << endl;
for_each(v.begin(), v.end(), print02());
cout << endl;
}
int main() {
test01();
system("pause");
return 0;
}
二、transform
機能の説明:
- コンテナを別のコンテナに移動します
関数プロトタイプ:
transform(iterator beg1, iterator end1, iterator beg2, _func);
// beg1ソースコンテナ開始イテレータ
// end1ソースコンテナ終了イテレータ
// beg2ターゲットコンテナ開始イテレータ
// _ func関数または関数オブジェクト
ソースコード:
// FUNCTION TEMPLATE transform
template <class _InIt, class _OutIt, class _Fn>
_CONSTEXPR20 _OutIt transform(const _InIt _First, const _InIt _Last, _OutIt _Dest, _Fn _Func) {
// transform [_First, _Last) with _Func
_Adl_verify_range(_First, _Last);
auto _UFirst = _Get_unwrapped(_First);
const auto _ULast = _Get_unwrapped(_Last);
auto _UDest = _Get_unwrapped_n(_Dest, _Idl_distance<_InIt>(_UFirst, _ULast));
for (; _UFirst != _ULast; ++_UFirst, (void) ++_UDest) {
*_UDest = _Func(*_UFirst);
}
_Seek_wrapped(_Dest, _UDest);
return _Dest;
}
ここでは、最初に元の関数の開始イテレーターと終了イテレーターを指定し、次にforループを指定します。
毎回、イテレータが指す値に対して関数演算を実行し、それをターゲットイテレータに配置します。
実行後、両方のイテレータは++操作を実行します。
例:
#include<vector>
#include<algorithm>
//常用遍历算法 搬运 transform
class TransForm
{
public:
int operator()(int val)
{
return val;
}
};
class MyPrint
{
public:
void operator()(int val)
{
cout << val << " ";
}
};
void test01()
{
vector<int>v;
for (int i = 0; i < 10; i++)
{
v.push_back(i);
}
vector<int>vTarget; //目标容器
vTarget.resize(v.size()); // 目标容器需要提前开辟空间
transform(v.begin(), v.end(), vTarget.begin(), TransForm());
for_each(vTarget.begin(), vTarget.end(), MyPrint());
}
int main() {
test01();
system("pause");
return 0;
}
注:輸送対象のコンテナは、事前にスペースを空ける必要があります。そうしないと、正常に移動できません。