MochiuWiki : SUSE, EC, PCB
案内
メインページ
最近の更新
おまかせ表示
MediaWiki についてのヘルプ
ツール
リンク元
関連ページの更新状況
特別ページ
ページ情報
We ask for
Donations
検索
個人用ツール
ログイン
Toggle dark mode
名前空間
ページ
議論
表示
閲覧
ソースを閲覧
履歴を表示
C++の基礎 - ラムダ式のソースを表示
提供: MochiuWiki : SUSE, EC, PCB
←
C++の基礎 - ラムダ式
あなたには「このページの編集」を行う権限がありません。理由は以下の通りです:
この操作は、次のグループのいずれかに属する利用者のみが実行できます:
管理者
、new-group。
このページのソースの閲覧やコピーができます。
== 概要 == ラムダ式(無名関数(anonymous function, nameless function)、匿名関数)とは、関数を定義するための記法、文法のことである。<br> <br> C++では、ラムダ式はC++11からサポートされた。g++コンパイラを使用する場合は、以下のようにC++11を有効にする必要がある。<br> また、C++11とC++14で仕様が異なる。C++14版は、より高度になっている。<br> g++49 -std=c++11 lambda.cpp c++ -std=c++11 lambda.cpp <br> C++のラムダ式以下の特徴がある。<br> * 関数オブジェクトであり、生成されたクラスのoperator()になる。 * std::functionに代入できる。 * STLの引数に使用できる。また、コールバック関数等の引数としてラムダ式を直接記述できる。 * ローカル変数をキャプチャできる。 * 引数や戻り値の型推論(auto)も利用できる。 <br><br> == ラムダ式の文法 == <syntaxhighlight lang="c++"> int main(int argc, char *argv[]) { [] // ラムダキャプチャー () // パラメータ定義節 {} // 複合ステートメント () // 関数呼び出し式 ; return 0; } </syntaxhighlight> <br><br> == 最小のラムダ式の定義 == <syntaxhighlight lang="c++"> int main(int argc, char *argv[]) { auto func = [](){}; return 0; } </syntaxhighlight> <br> 引数は省略可能であるため、さらに省略できる。<br> <syntaxhighlight lang="c++"> int main(int argc, char *argv[]) { auto func = []{}; return 0; } </syntaxhighlight> <br><br> == 最小のラムダ式の呼び出し == ラムダ式を呼び出すには、関数呼び出し式()を使用する。<br> <syntaxhighlight lang="c++"> int main(int argc, char *argv[]) { [](){}(); return 0; } </syntaxhighlight> <br><br> == サンプルコード == ===== ラムダ式で書くHello World ===== <syntaxhighlight lang="c++"> #include <iostream> int main(int argc, char const* argv[]) { []{ std::cout << "Hello World" << std::endl;}(); return 0; } </syntaxhighlight> <br> ===== ラムダ式を変数に代入する ===== ラムダ式を変数に代入することができる。関数ポインタのような感覚で呼び出せる。<br> <syntaxhighlight lang="c++"> #include <iostream> int main(int argc, char const* argv[]) { auto func = []{std::cout << "Hello world" << std::endl;}; func(); //ラムダ式の呼び出し return 0; } </syntaxhighlight> <br> ===== ラムダ式を関数に渡す ===== ラムダ式を別の関数に渡すことができる。(コールバック関数)<br> <syntaxhighlight lang="c++"> #include <iostream> template<typename Func> void f(Func func) { func(); } int main(int argc, const char *argv[]) { f([]{std::cout << "Hello world" << std::endl;}); return 0; } </syntaxhighlight> <br> ===== ラムダ式に引数を与える ===== <syntaxhighlight lang="c++"> #include <iostream> #include <string> int main(int argc, const char *argv[]) { [](const string &str) // 引数の定義 { // 関数本体 std::cout << str << std:endl; } ("I am Argument!"); // 関数呼び出しと引数 return 0; } </syntaxhighlight> <br> ===== ラムダ式で戻り値を返す ===== ラムダ式は、戻り値を返すことができる。<br> 1つ目は、明示的に戻り値の型を定義していない。<br> 2つ目は、明示的に戻り値の型を定義している。アロー演算子の記法([]()->型)で表現している。<br> <syntaxhighlight lang="c++"> #include <iostream> int main(int argc, const char *argv[]) { auto a = []{return 0;}; // 戻り値を推測させる auto b = []() -> float {return 3.14;}; // 戻り値を明示的に定義する std::cout << a << std::endl; std::cout << b << std::endl; return 0; } </syntaxhighlight> <br> ===== 変数のキャプチャ ===== ラムダ式は、式が定義される関数のスコープの変数をキャプチャできる。<br> JavaScriptでいうクロージャが、スコープにある変数を参照できることをイメージすること。<br> <syntaxhighlight lang="c++"> #include <iostream> #include <string> int main(int argc, char const* argv[]) { string x = "I am string"; [&]{std::cout << x << std::endl;}(); // 参照 [=]{std::cout << x << std::endl;}(); // コピー return 0; } </syntaxhighlight> <br> ===== 参照の場合の代入 ===== 参照での代入とコピーでの代入を行う。<br> <syntaxhighlight lang="c++"> #include <iostream> #include <string> int main(int argc, const char *argv[]) { string s1 = "I am s1"; [&]{s1 = "Overwrite s1!";}(); //string s2 = "I am s2"; //[=]{s1 = "Overwrite s2!";}(); C++11ではコンパイルエラーが起きる std::cout << s1 << std::endl; //std::cout << s2 << std::endl; return 0; } </syntaxhighlight> <br> ===== mutable ===== コピーでの代入では、変数を書き変えることができないが、mutableを使用することで、ラムダ式の中だけ変数を書き変えることができる。<br> しかし、コピーのため、元の変数の値は変更できない。<br> mutableを指定した時、ラムダ式の引数リストの括弧は省略できない。<br> <syntaxhighlight lang="c++"> #include <iostream> #include <string> int main(int argc, const char *argv[]) { std::string s1 = "I am s1"; [=]() mutable {s1 = "Overwrite s1!"; std::cout << s1 << std::endl;}(); std::cout << s1 << std::endl; return 0; } </syntaxhighlight> <br> また、mutableを指定した時、明示的に戻り値を指定する場合は、以下のようにする。<br> <syntaxhighlight lang="c++"> auto dRet = []() mutable -> double {return 3.14;}; </syntaxhighlight> <br> ===== キャプチャの指示 ===== ラムダキャプチャ[]には、変数ごとにキャプチャの方法(コピーまたは参照)を指定できる。<br> <syntaxhighlight lang="c++"> #include <iostream> int main(int argc, const char *argv[]) { int a = 0, b = 0; [a, &b]() mutable {a = 1; b = 1;}(); std::cout << a << std::endl; // 0 std::cout << b << std::endl; // 1 return 0; } </syntaxhighlight> <br> また、一部の変数だけ指定して、残りは、キャプチャのデフォルトを指定することができる。<br> <syntaxhighlight lang="c++"> #include <iostream> int main(int argc, const char *argv[]) { int a = 0, b = 0, c = 0, d = 0; // a, bを参照、それ以外はコピー [=, &a, &b]() mutable {}(); // a, bはコピー、それ以外は参照 [&, a, b]() mutable {}(); return 0; } </syntaxhighlight> <br> また、以下のように、デフォルトと同じキャプチャは指定できない。<br> <syntaxhighlight lang="c++"> int a = 0, b = 0; [&, &a]{}(); // エラー [=, a]{}(); // エラー [a, a]{}(); // エラー </syntaxhighlight> <br> ===== thisポインタとキャプチャ ===== thisポインタは、ポインタであるため、キャプチャがコピーでも参照でも、以下のように変数iは変更される。<br> <syntaxhighlight lang="c++"> #include <iostream> typedef struct tag_S { int i; void f() { [=]{this->i = 1;}(); } }S; int main(int argc, char const* argv[]) { S s; s.f(); return 0; } </syntaxhighlight> <br> ===== ラムダ式を返す ===== std::functionを使用することで、ラムダ式を関数から返すことができる。<br> キャプチャがコピーであるため、変数strは破棄されない。<br> <syntaxhighlight lang="c++"> #include <iostream> #include <string> #include <functional> std::function<void()> f() { std::string str = "Hoge"; return [=]{std::cout << str << std::endl;}; } int main(int argc, const char *argv[]) { auto func = f(); func(); // 代入して呼び出し f()(); // 代入せずに呼び出し return 0; } </syntaxhighlight> <br><br> __FORCETOC__ [[カテゴリ:C++]]
C++の基礎 - ラムダ式
に戻る。
案内
メインページ
最近の更新
おまかせ表示
MediaWiki についてのヘルプ
ツール
リンク元
関連ページの更新状況
特別ページ
ページ情報
We ask for
Donations
Collapse