C++
 Computer >> コンピューター >  >> プログラミング >> C++

C++のラムダ式の基本と使い方を徹底解説

C++のSTLには、std::for_eachのような便利な汎用関数が数多く含まれています。しかし残念ながら、これらの関数は使い勝手がやや煩雑な場合があります。特に、特定の関数にしか使わない一意のファンクタ(関数オブジェクト)を適用したい場合には、その場限りの処理のためだけに名前空間内で関数を定義する必要があり、コードが冗長になりがちです。

このような問題を解決するのが「匿名関数(無名関数)」です。C++11ではラムダ式が導入され、その場で簡潔に匿名関数を作成できるようになりました。

ラムダ式の基本的な例

以下は、for_eachと組み合わせてラムダ式を使用するシンプルな例です。

#include<iostream>
#include<vector>
#include <algorithm> // for_each
using namespace std;

int main() {
    vector<int> myvector;
    myvector.push_back(1);
    myvector.push_back(2);
    myvector.push_back(3);

    for_each(myvector.begin(), myvector.end(), [](int x) {
        cout << x*x << endl;
    });
}

実行結果

1
4
9

この例では、ベクター内の各要素に対して2乗した値が出力されます。[](int x)の部分がラムダ式であり、各要素が引数xとして渡され、その2乗が表示されています。

ラムダ式の構成要素

引数の定義

(int x)の部分は、ラムダ式が呼び出される際に受け取る引数を定義しています。通常の関数と同様に、複数の引数を指定することも可能です。

キャプチャ(変数の捕捉)

[]の部分は、ローカルスコープからラムダ式の内部スコープへ変数を受け渡すために使用され、これを「キャプチャ」と呼びます。キャプチャの主な指定方法は以下の通りです。

  • []:何もキャプチャしない
  • [=]:使用するすべての変数を値渡しでキャプチャ
  • [&]:使用するすべての変数を参照渡しでキャプチャ
  • [x, &y]xは値渡し、yは参照渡しで個別に指定

戻り値の型指定

単純なラムダ式であれば、戻り値の型はコンパイラが自動的に推論してくれます。しかし、明示的に型を指定したい場合は、以下のように->を使って記述します。

[](int x) -> double {
    return x / 2.0;
}

このように書くことで、戻り値がdouble型であることを明確に示せます。

まとめ

ラムダ式を使用することで、その場限りの小さな処理を簡潔に記述でき、コードの可読性と保守性が大幅に向上します。STLのアルゴリズム関数と組み合わせれば、ファンクタを別途定義する手間も省け、よりモダンで効率的なC++プログラミングが可能になります。

  1. C++で点集合の線対称(ラインリフレクション)を判定するアルゴリズム

    問題概要2次元平面上にn個の点が与えられます。このとき、y軸に平行な直線で全ての点を鏡映(反射)した結果が、元の点集合と完全に一致するような直線が存在するかどうかを判定します。言い換えれば、ある直線を対称軸として全ての点を反転させたとき、反転後の点の集合が元の集合と同一になるかを確認する問題です。例えば、入力が points = [[1,1],[-1,1]] の場合を考えてみましょう。この場合、x = 0 の直線(y軸)を対称軸とすると、点 (1,1) は (-1,1) へ、(-1,1) は (1,1) へと移ります。点集合全体としては変化がないため、出力は true となります。解法のポイン

  2. C++で解く対角トラバースII:リストのリストを対角順に出力する方法

    問題の概要 「リストのリスト」である nums が与えられたとき、そのすべての要素を対角順(ダイアゴナルオーダー)に並べて出力するのがこの問題の目的です。 たとえば、次のような行ごとに長さの異なる配列(ジャグ配列)が入力として与えられた場合を考えてみましょう。 このとき、期待される出力は次のとおりです。 [1, 6, 2, 8, 7, 3, 9, 4, 12, 10, 5, 13, 11, 14, 15, 16] 解法のアプローチ この問題は、各要素を「値と座標のセット」として一旦記録し、対角線ごとの順序になるようにソートし直すことで解けます。具体的な手順は以下の通りです。 結果を格納す