C++11 - 3 - ラムダ式

C++

序文:

Vue框架:プロジェクトからVue の
OJ算法系列:魔法のトリックを学ぶ - アルゴリズムの詳細な説明
Linux操作系统:Fenghou Qimen - linux

呼び出し可能なオブジェクト:

  • 意味: パラメータを渡し、それらを処理し、結果を渡す機能を持つオブジェクト
  • 分類:
    1. 関数:
    2. 関数ポインタ:
    3. ファンクターオブジェクト:
    4. ラムダ式:
  • 例:
//1, 函数:
void fmin(int x, int y){
    
    
	return x<y?x:y;
}
//2,函数指针:
void func(int, int) = fmin();
func(1, 2);
//3,仿函数对象:
struct IntLess{
    
    
	bool operator()(int &x, int &y){
    
    
		return x<y?x:y; 
	}
}
IntLess(1, 2);
//4,简易lambda表达式:
auto function = [](int x, int y){
    
    
	return x<y?x:y;
};
function(1, 2);

ラムダ式:

フォーマット:

  • 2 つ、3 つ、4 つ、または 5 つの部分で構成できます。
//附加说明的五部分:附加关键词一般为mutable、noexcept
auto func = [](int x, int y)mutable->int{
    
    
	return x<y?x:y;
}
//完整的四部分:
auto func1 = [](int x, int y)->int{
    
    
	return x<y?x:y;
};
//省略返回类型,可自动推导返回类型
auto func2 = [](int x, int y){
    
    
	return x<y?x:y;
};
//当不需要参数时候,可省略参数
auto func3 = []{
    
    
	cout<< "hello world"<< endl;
};
  • 4 つの部分を完了します。
    1. 【キャプチャーリスト】
    2. (パラメータリスト)
    3. -> 戻り値の型
    4. {関数本体}
  • 追加部分: 追加のキーワード
  • ラムダ式に必要な 2 つの部分: []{}
    省略できる 2 つの部分: ()->

捕獲リスト:

  • 意味:ラムダ式にパラメータを渡す場合、()内に渡せるのは値のみで、参照やアドレスを渡したい場合はキャプチャリストを使用する必要がある
  • 機能: ラムダ式と同じスコープ内のローカル変数をキャプチャします。
  • キャプチャフォーム:
    1. 価値による捕捉
    2. 参照渡しキャプチャ
  • キャプチャ範囲の要件:
    1. ラムダ式と同じスコープ内
    2. ローカル変数のみをキャプチャできます
    3. 同じ変数の場合、値のキャプチャと参照のキャプチャを同時に行うことはできません
  • キャプチャフォーム:
    1. 引用のキャプチャ:
      1. 現在のスコープ内の変数への参照をキャプチャします:
        &a ->{}
      2. 現在のスコープ内のすべての変数への参照をキャプチャします:
        & ->{}
    2. 値によるキャプチャ:
      1. 現在のスコープ内の変数の値をキャプチャします:
        a ->{}
      2. 現在のスコープ内のすべての変数値をキャプチャします:
        = ->{}

追加のキーワード:

  • mutable キーワード:
    1. 機能:値キャプチャで取得される変数はデフォルトでは const なので、書きたい場合は添付キーワード mutable を追加する必要があります
    2. 配置: (仮パラメータ) の直後に追加、つまり Mutable を使用キーワードを追加する必要があります (仮パラメータリスト)
  • 例:
//报错:常量不可修改
int main(){
    
    
	int x = 0;
	auto func = [=](){
    
    
		x++;
		cout<<x<<endl;
	};
	cout<<x<<endl;
}

//()mutable
int main(){
    
    
	int x = 0;
	auto func = [=]()mutable{
    
    
		x++;
		cout<<x<<endl;
	};
	cout<<x<<endl;
}

decltype 式の本質:

  • ラムダ式は本質的にファンクタークラスです
  • range の本質がイテレータであるのと同じように、
  • C++11 では、変数の型を推論するための演算子記号 decltype も提供しています。
auto func = [](int x, int y){
    
    
	return x<y?x:y;
};
cout<< decltype(func).name();
  • decltype と auto の違いは次のとおりです。
    1. decltype は、関数パラメータなど、変数の型を宣言する必要がある場合に使用されます。
    2. auto は、単に使用するなど、変数の型を宣言する必要がない場合に使用されます。

  • decltype は以下を使用します。

auto func1 = []{
    
    cout<<"极简lambda"<<endl;};
auto func2 = func1;
decltype(func1) func3 = func1;

キャプチャリストとパラメータリストの比較:

物質:

  • ラムダ式はファンクター クラスに変換されます。
    1. キャプチャリストはクラスのメンバー変数に変換されます。
    2. パラメータは内部関数パラメータに変換されます

範囲:

  • 仮パラメータリスト () + mutable、パラメータのソースは任意の変数にすることができます。もちろん、mutable のスコープは追加されず、書き込み権限は失われます
  • キャプチャ リストによってキャプチャされるオブジェクトは、同じスコープ内のローカル変数のみにすることができます
  • 同じスコープ内のローカル変数を操作する場合、()+mutable と [] は同じ効果があります。

呼び出しオブジェクトの比較:

ラムダ:

  • ラムダ式は、関数/関数ポインター/ファンクター オブジェクトよりも高速に記述できます。

    これに似た、クラスのさまざまなフィールドに基づいてクラスのオブジェクトを並べ替えるコードを記述するのに適しています。

  • 以下に製品クラスを示します。製品の価格/評価/名前に従って製品オブジェクトを並べ替えるように依頼します。

  • 商品カテゴリー:

class Goods{
    
    
	private:
		int price;
		double evaluate;
		char* name;
	public:
		//八大默认函数,自动补全。
		Goods(int _price, double _evaluete, char* _name){
    
    
			price = _price;
			evaluete = _evaluete;
			name = _name;
		}
};
  • 商品の並べ替え - ラムダ式に基づく:
vector<Goods> v{
    
    {
    
    1, 1.0, "a"}, {
    
    2, 2.0, "b"}, {
    
    3, 3.0, "c"}, {
    
    4, 4.0, "d"}};
sort(v.begin(), v.end(), [](Goods &a, Goods &b){
    
    
		return a.price > b.price;
	});
sort(v.begin(), v.end(), [](Goods &a, Goods &b){
    
    
		return a.price < b.price;
	});
sort(v.begin(), v.end(), [](Goods &a, Goods &b){
    
    
		return a.evaluete > b.evaluete;
	});
sort(v.begin(), v.end(), [](Goods &a, Goods &b){
    
    
		return a.evaluete < b.evaluete;
	});
sort(v.begin(), v.end(), [](Goods &a, Goods &b){
    
    
		return strcmp(a.name, b.name);
	});
sort(v.begin(), v.end(), [](Goods &a, Goods &b){
    
    
		return -1*strcmp(a.name, b.name);
	});

関数ポインタ:

  • 項目の並べ替え - 関数/関数ポインターに基づいて:
bool ComparePriceLess(Goods &a, Goods &b){
    
    
	return a.price < b.price;
}
bool ComparePriceMore(Goods &a, Goods &b){
    
    
	return a.price < b.price;
}
bool CompareEvaluateLess(Goods &a, Goods &b){
    
    
	return a.price < b.price;
}
bool CompareEvaluateMore(Goods &a, Goods &b){
    
    
	return a.price < b.price;
}
bool CompareNameLess(Goods &a, Goods &b){
    
    
	return a.price < b.price;
}
bool CompareNameMore(Goods &a, Goods &b){
    
    
	return a.price < b.price;
}
vector<Goods> v{
    
    {
    
    1, 1.0, "a"}, {
    
    2, 2.0, "b"}, {
    
    3, 3.0, "c"}, {
    
    4, 4.0, "d"}};
sort(v.begin(), v.end(), ComparePriceLess);
sort(v.begin(), v.end(), ComparePriceMore);
sort(v.begin(), v.end(), CompareEvaluateLess);
sort(v.begin(), v.end(), CompareEvaluateMore);
sort(v.begin(), v.end(), CompareNameLess);
sort(v.begin(), v.end(), CompareNameMore);
}

ファンクターオブジェクト:

  • 項目の並べ替え - ファンクターベース:
struct ComparePriceLess{
    
    
	bool operator()(Goods &a, Goods &b){
    
    
		return a.price < b.price;
	}
};
struct ComparePriceMore){
    
    
	bool operator()(Goods &a, Goods &b){
    
    
		return a.price > b.price;
	}
};
struct CompareEvaluateLess{
    
    
	bool operator()(Goods &a, Goods &b){
    
    
		return a.evaluate < b.evaluate;
	}
};
struct CompareEvaluateLess{
    
    
	bool operator()(Goods &a, Goods &b){
    
    
		return a.evaluate > b.evaluate;
	}
};
struct CompareNameLess{
    
    
	bool operator()(Goods &a, Goods &b){
    
    
		return -1*strcmp(a.name, b.name);
	}
};
struct CompareNameLess{
    
    
	bool operator()(Goods &a, Goods &b){
    
    
		return strcmp(a.name, b.name);
	}
};
vector<Goods> v{
    
    {
    
    1, 1.0, "a"}, {
    
    2, 2.0, "b"}, {
    
    3, 3.0, "c"}, {
    
    4, 4.0, "d"}};
sort(v.begin(), v.end(), ComparePriceLess());
sort(v.begin(), v.end(), ComparePriceMore());
sort(v.begin(), v.end(), CompareEvaluateLess());
sort(v.begin(), v.end(), CompareEvaluateMore());
sort(v.begin(), v.end(), CompareNameLess());
sort(v.begin(), v.end(), CompareNameMore());
};

おすすめ

転載: blog.csdn.net/buptsd/article/details/126883125