ラムダ式の構文Lambda Expression Syntax

この記事では、ラムダ式の構文と構造体要素を説明します。This article demonstrates the syntax and structural elements of lambda expressions. ラムダ式の詳細については、「 ラムダ式」を参照してください。For a description of lambda expressions, see Lambda Expressions.

関数オブジェクトとラムダFunction Objects vs. Lambdas

コードを記述する場合、特に C++ 標準ライブラリアルゴリズムを使用する場合は、関数ポインターと関数オブジェクトを使用して問題を解決し、計算を実行します。When you write code, you probably use function pointers and function objects to solve problems and perform calculations, especially when you use C++ Standard Library algorithms. 関数ポインターと関数オブジェクトには、それぞれに利点と欠点があります。たとえば、関数ポインターは、最小限の構文オーバーヘッドで済みますが、スコープ内の状態を保持しません。関数オブジェクトは、状態を保持できますが、クラス定義の構文オーバーヘッドが必要となります。Function pointers and function objects each have advantages and disadvantages—for example, function pointers have minimal syntactic overhead but do not retain state within a scope, and function objects can maintain state but require the syntactic overhead of a class definition.

ラムダは、関数ポインターと関数オブジェクトの両方の利点を持ち、それらの欠点を回避できます。A lambda combines the benefits of function pointers and function objects and avoids their disadvantages. ラムダは、関数オブジェクトのように柔軟性があり状態を保持できますが、関数オブジェクトとは異なり、その簡潔な構文には明示的なクラス定義は必要ありません。Like a function objects, a lambda is flexible and can maintain state, but unlike a function object, its compact syntax doesn't require an explicit class definition. ラムダを使用すると、同等の関数オブジェクトのコードよりも使いやすくエラーが発生しにくいコードを作成できます。By using lambdas, you can write code that's less cumbersome and less prone to errors than the code for an equivalent function object.

次の例では、ラムダの使用と関数オブジェクトの使用を比較しています。The following examples compare the use of a lambda to the use of a function object. 最初の例では、ラムダを使用して vector オブジェクト内の各要素が偶数か奇数であるかをコンソールに出力します。The first example uses a lambda to print to the console whether each element in a vector object is even or odd. 2 番目の例では、関数オブジェクトを使用して同じタスクを行っています。The second example uses a function object to accomplish the same task.

例 1: ラムダの使用Example 1: Using a Lambda

この例では、ラムダを for_each 関数に渡します。This example passes a lambda to the for_each function. ラムダは、vector オブジェクト内の各要素が偶数か奇数かを示す結果を出力します。The lambda prints a result that states whether each element in a vector object is even or odd.

コードCode

// even_lambda.cpp
// compile with: cl /EHsc /nologo /W4 /MTd
#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;

int main()
{
   // Create a vector object that contains 9 elements.
   vector<int> v;
   for (int i = 1; i < 10; ++i) {
      v.push_back(i);
   }

   // Count the number of even numbers in the vector by
   // using the for_each function and a lambda.
   int evenCount = 0;
   for_each(v.begin(), v.end(), [&evenCount] (int n) {
      cout << n;
      if (n % 2 == 0) {
         cout << " is even " << endl;
         ++evenCount;
      } else {
         cout << " is odd " << endl;
      }
   });

   // Print the count of even numbers to the console.
   cout << "There are " << evenCount
        << " even numbers in the vector." << endl;
}
1 is odd
2 is even
3 is odd
4 is even
5 is odd
6 is even
7 is odd
8 is even
9 is odd
There are 4 even numbers in the vector.

説明Comments

この例では、 for_each 関数の3番目の引数はラムダです。In the example, the third argument to the for_each function is a lambda. [&evenCount] の部分は、式の capture 句を指定します。(int n) はパラメーター リストを指定します。残りの部分は、式の本体を指定します。The [&evenCount] part specifies the capture clause of the expression, (int n) specifies the parameter list, and remaining part specifies the body of the expression.

例 2: 関数オブジェクトの使用Example 2: Using a Function Object

ラムダは、前の例よりも拡張するのがはるかに複雑になる場合があります。Sometimes a lambda would be too unwieldy to extend much further than the previous example. 次の例では、ラムダの代わりに関数オブジェクトを for_each 関数と共に使用して、例1と同じ結果を生成します。The next example uses a function object instead of a lambda, together with the for_each function, to produce the same results as Example 1. どちらの例でも vector オブジェクトに含まれる偶数の数を格納します。Both examples store the count of even numbers in a vector object. 操作の状態を保持するために、FunctorClass クラスはメンバー変数の参照として m_evenCount 変数を格納します。To maintain the state of the operation, the FunctorClass class stores the m_evenCount variable by reference as a member variable. 操作を実行するために、は FunctorClass 関数呼び出し演算子である operator () を実装します。To perform the operation, FunctorClass implements the function-call operator, operator(). Microsoft C++ コンパイラは、サイズとパフォーマンスに匹敵するコードを例1のラムダコードに生成します。The Microsoft C++ compiler generates code that is comparable in size and performance to the lambda code in Example 1. ここで紹介したような基本的な問題の場合は、おそらく、より単純なラムダのデザインの方が関数オブジェクトよりも適切です。For a basic problem like the one in this article, the simpler lambda design is probably better than the function-object design. ただし、後で大幅な機能拡張が必要となる可能性がある場合は、コードの保守が容易になるように、関数オブジェクトのデザインを使用します。However, if you think that the functionality might require significant expansion in the future, then use a function object design so that code maintenance will be easier.

演算子 () の詳細については、「関数呼び出し」を参照してください。For more information about the operator(), see Function Call. For_each関数の詳細については、「 for_each」を参照してください。For more information about the for_each function, see for_each.

コードCode

// even_functor.cpp
// compile with: /EHsc
#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;

class FunctorClass
{
public:
    // The required constructor for this example.
    explicit FunctorClass(int& evenCount)
        : m_evenCount(evenCount) { }

    // The function-call operator prints whether the number is
    // even or odd. If the number is even, this method updates
    // the counter.
    void operator()(int n) const {
        cout << n;

        if (n % 2 == 0) {
            cout << " is even " << endl;
            ++m_evenCount;
        } else {
            cout << " is odd " << endl;
        }
    }

private:
    // Default assignment operator to silence warning C4512.
    FunctorClass& operator=(const FunctorClass&);

    int& m_evenCount; // the number of even variables in the vector.
};

int main()
{
    // Create a vector object that contains 9 elements.
    vector<int> v;
    for (int i = 1; i < 10; ++i) {
        v.push_back(i);
    }

    // Count the number of even numbers in the vector by
    // using the for_each function and a function object.
    int evenCount = 0;
    for_each(v.begin(), v.end(), FunctorClass(evenCount));

    // Print the count of even numbers to the console.
    cout << "There are " << evenCount
        << " even numbers in the vector." << endl;
}
1 is odd
2 is even
3 is odd
4 is even
5 is odd
6 is even
7 is odd
8 is even
9 is odd
There are 4 even numbers in the vector.

関連項目See also

ラムダ式Lambda Expressions
ラムダ式の例Examples of Lambda Expressions
生みgenerate
generate_ngenerate_n
for_eachfor_each
例外の指定 (throw)Exception Specifications (throw)
コンパイラの警告 (レベル 1) C4297Compiler Warning (level 1) C4297
Microsoft 固有の修飾子Microsoft-Specific Modifiers