ジェネリックプログラミング講義14のC ++開発[一般的に使用されるトラバーサルアルゴリズム]

一、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;
}

注:輸送対象のコンテナは、事前にスペースを空ける必要があります。そうしないと、正常に移動できません。

 

おすすめ

転載: blog.csdn.net/Kukeoo/article/details/114108474