記事ディレクトリ
C++ では関数内で関数を定義することもできますか? これは不可能ですが、関数オブジェクトを定義することは可能です。従来の方法で関数オブジェクトを定義すると、関数クラスを自分で記述する必要があり、不便です。しかし、C++11のリリース後は、関数内に「関数」(実際には「関数オブジェクト」)を簡単に定義できるようになりました。
Part.I の例
以下は簡単な例で、main
関数内で 2 つの「関数オブジェクト」が定義されており、1 つはprint
2 次元ベクトルを出力するために使用され、もう 1 つは、cmp
sort 関数のソート基準を提供するために使用されます。 2番目の要素のサイズ 大きいものから小さいものへ並べます。
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
int main()
{
auto print = [](vector<vector<int>> a) {
for(int i=0;i<a.size();i++) {
for(int j=0;j<a[i].size();j++)
cout<<a[i][j]<<" ";
cout<<endl;
}
};
vector<vector<int>> A;
vector<int> B({
1,2}); A.push_back(B);
B=vector<int>({
2,1}); A.push_back(B);
B=vector<int>({
3,6}); A.push_back(B);
cout<<"----------Origin---------"<<endl;
print(A);
auto cmp = [](const vector<int> a, const vector<int> b){
return a[1]>b[1];};
sort(A.begin(), A.end(), cmp);
cout<<"----------After Sorted---------"<<endl;
print(A);
getchar();
return 0;
}
結果の出力は次のようになります。
----------Origin---------
1 2
2 1
3 6
----------After Sorted---------
3 6
1 2
2 1
第Ⅱ部 説明
この文言の説明:
- 上記のコードは、古い標準の自動変数 (スペースの自動割り当てと自動解放) の意味ではなく、C++ 11 では新しい機能を持っています。変数が宣言されると、変数の初期化値
auto
から導出され、変数の型の値を指定します。 auto print = [](xx) { };
は のないラムダ式です-> ret
。ラムダ式については後で詳しく紹介します。- Lambda は名前のない関数オブジェクトを生成するため、関数内で直接呼び出すことはできません。ただし、「この名前のない関数オブジェクトにエイリアスを付ける」と、エイリアスを介して呼び出すことができます。
第 I 章 ラムダ式
ラムダは関数型プログラミングの概念から派生したもので、最新のプログラミング言語の機能です。C++11 ではついにラムダが追加されました。
ラムダ式には次の利点があります。
- 宣言型プログラミング スタイル: 追加の名前付き関数または関数オブジェクトを作成せずに、ターゲット関数または関数オブジェクトを匿名でその場で定義します。可読性と保守性に優れた、より直接的な方法でプログラムを作成します。
- 簡潔さ: 追加の関数や関数オブジェクトを記述する必要がないため、コードの拡張や関数の分散が回避され、開発者は当面の問題により集中できるようになり、生産性も向上します。
- 必要なときに必要な場所に関数クロージャを実装すると、プログラムがより柔軟になります。
ラムダ式は匿名関数を定義し、特定のスコープ内の変数をキャプチャできます。ラムダ式の文法形式は次のように簡単に要約できます。
[ capture ] ( params ) opt -> ret {
body; };
の
- Capture はキャプチャ リスト、空は変数がキャプチャされないことを意味します。
&
外側のスコープ内のすべての変数をキャプチャし、関数本体内の参照として使用することを意味します (参照によるキャプチャ)。=
外側のスコープ内のすべての変数をキャプチャして使用することを意味します。 (値によるキャプチャ) で使用される関数本体内のコピーとして;=,&foo
外側のスコープ内のすべての変数を値によってキャプチャし、foo
変数を参照によってキャプチャすることを意味します。他の変数をキャプチャせずに、bar
value によって変数をキャプチャすることは、ラムダ式が現在のクラスのメンバー関数と同じアクセス権を持つように、現在のクラスの this ポインターをキャプチャすることを意味します。または がすでに使用されている場合、このオプションはデフォルトで追加されます。これをキャプチャする目的は、lamda で現在のクラスのメンバー関数とメンバー変数を使用することです。bar
this
&
=
- params はパラメータリストです。
- opt は関数のオプションです。
- ret は戻り値の型です。
- body は関数本体です