開発
[](){}C++11のラムダについて
Taisei Igarashi
こんばんは、アルバイトの五十嵐です。
外がだんだん暑くなり、夏の訪れを感じさせます。個人的に冬が好きなので余り嬉しくはないのですが……
私は冬が好きです。
冬と言えばおでんですね。
”[]()->int{};”この構文みておでんを感じませんか?実はこのコード、C++11ではコンパイルできるのです!
という事で余り詳しくはないのですがC++11のラムダ式について軽く書いていこうと思います。
ラムダとは簡単に言うと
計算を処理して一つの値を返すが、名前がない関数
と、認識しています。詳しくは省きますが、名前のない関数オブジェクトだという事です。
最小のラムダ
[](){};
文法上は正しく動きます。当然それ以上の意味はありません。
ではそれぞれの意味を書いて行きましょう
[] :変数のキャプチャを指定
() :内部に引数を記述する
{} :内部に関数の本文を記述する
では基本なHello Worldから書いてみましょう
[]{ std::cout <<"Hello World"<< std::endl ; }();
}の後の()は関数を呼ぶ演算子です。なのでこの文だけで表示されます。
ですが当然このままでは利用価値がありません。少なくとも変数として持ちたいです。
そこで登場するのがauto型です。auto型を用いると以下のような文になります
auto func=[]{ std::cout <<"Hello World"<< std::endl ; }; func();
簡単ですね。
では()の中に引数を記述してみましょう。
auto func = [](int n) -> int{↲ cout<<"Hello, function(1)"<<endl;↲ };↲ func(13);
簡単ですね。従来の関数をそんなに変わりはありません。
さて、ここまできてやっと[]の紹介です。キャプチャとは何でしょうか?
無名関数中で無名関数定義域の変数変数を扱いたいと思いますよね。
そこで方法は3種類あります。
・引数として渡す
・[=]とする
・[&]とする
それぞれ特性があります、とりあえず以下のコードをご覧ください。
#include using namespace std; int main(){ int x=1; cout<<" (0)x="<<x<<endl; [](int n){ cout<<"arg(1)x="<<n<<endl; n++; cout<<"arg(2)x="<<n<<endl; }(x); cout<<" (3)x="<<x<<endl; [=](){ cout<<"[=](4)x="<<x<<endl; //x++; error! cout<<"[=](5)x="<<x<<endl; }(); cout<<" (6)x="<<x<<endl; [&](){ cout<<"[&](7)x="<<x<<endl; x++; cout<<"[&](8)x="<<x<<endl; }(); cout<<" (9)x="<<x<<endl; return 0; }
実行結果
(0)x=1 arg(1)x=1 arg(2)x=2 (3)x=1 [=](4)x=1 [=](5)x=1 (6)x=1 [&](7)x=1 [&](8)x=2 (9)x=2
お分かりいただけだでしょうか?
引数の場合
・引数に渡しているので変数の生存期間は関数内です。
[=]の場合
・コピーなのでx変数は使えますがconstなので書き換えようとするとコンパイルエラーが発生します。
(もし書き換えたい場合は[=]() mutable{と記述します)
[&]の場合
・参照渡しなのでx変数は使えます。書き換えも可能です。関数外でも変数の変更は維持されます。
ラムダ式はどのように使われるのか?
int array[] = {1, 2, 3, 4, 5}; int sum = 0; for_each(begin(array), end(array), [&](int v){ sum += v; }); cout<<sum<<endl;
これはarrayの総和を求める文です。
for_eachなどの中で簡単に関数を記述するだけで、求まります。
コードが綺麗になりいいですね。
深く行くと何処までも言ってしまうので今回は簡単にラムダに関して
は筆を置かせて頂きます。
みなさんもC++11を触ってみてはどうでしょうか?
浅学ですが私はC++/C++11を面白い言語だと思っています。
五十嵐