「C++の基礎 - クロージャ」の版間の差分

提供:MochiuWiki - SUSE, Electronic Circuit, PCB
ナビゲーションに移動 検索に移動
(ページの作成:「== 概要 == C++では、クロージャを作成することができる。<br> クロージャとは、環境(状態)を持った関数オブジェクトのようなも…」)
 
(文字列「__FORCETOC__」を「{{#seo: |title={{PAGENAME}} : Exploring Electronics and SUSE Linux | MochiuWiki |keywords=MochiuWiki,Mochiu,Wiki,Mochiu Wiki,Electric Circuit,Electric,pcb,Mathematics,AVR,TI,STMicro,AVR,ATmega,MSP430,STM,Arduino,Xilinx,FPGA,Verilog,HDL,PinePhone,Pine Phone,Raspberry,Raspberry Pi,C,C++,C#,Qt,Qml,MFC,Shell,Bash,Zsh,Fish,SUSE,SLE,Suse Enterprise,Suse Linux,openSUSE,open SUSE,Leap,Linux,uCLnux,Podman,電気回路,電子回路,基板,プリント基板 |description={{PAGENAME}} - 電子回路とSUSE Linuxに関する情報 | This pag…)
101行目: 101行目:
  </syntaxhighlight>
  </syntaxhighlight>
<br><br>
<br><br>
{{#seo:
|title={{PAGENAME}} : Exploring Electronics and SUSE Linux | MochiuWiki
|keywords=MochiuWiki,Mochiu,Wiki,Mochiu Wiki,Electric Circuit,Electric,pcb,Mathematics,AVR,TI,STMicro,AVR,ATmega,MSP430,STM,Arduino,Xilinx,FPGA,Verilog,HDL,PinePhone,Pine Phone,Raspberry,Raspberry Pi,C,C++,C#,Qt,Qml,MFC,Shell,Bash,Zsh,Fish,SUSE,SLE,Suse Enterprise,Suse Linux,openSUSE,open SUSE,Leap,Linux,uCLnux,Podman,電気回路,電子回路,基板,プリント基板
|description={{PAGENAME}} - 電子回路とSUSE Linuxに関する情報 | This page is {{PAGENAME}} in our wiki about electronic circuits and SUSE Linux
|image=/resources/assets/MochiuLogo_Single_Blue.png
}}


__FORCETOC__
__FORCETOC__
[[カテゴリ:C++]]
[[カテゴリ:C++]]

2024年10月14日 (月) 10:42時点における版

概要

C++では、クロージャを作成することができる。
クロージャとは、環境(状態)を持った関数オブジェクトのようなものである。

作成のポイントとして、ラムダ式をコピーキャプチャとした上でmutableにすることである。
クラスのメンバ変数等を使用せずに状態を保持できるため、大変便利なものといえる。


サンプルコード

 #include <iostream>
 
 auto func()
 {
    int x = 0;
    return [=]() mutable -> void
           {
              x++; std::cout << x << std::endl;
           };
 }
  
 int main()
 {
    auto f1 = func();
    f1();
    f1();
    f1();
 
    auto f2 = func();
    f2();
    f2();
    f2();
 }


出力
1
2
3
1
2
3


環境を共有する複数の処理を行う場合、引数で場合分けをする方がよい。
なお、参照キャプチャは、オブジェクトを複数個生成する場合は使用できない。

 #include <iostream>
 
 auto func()
 {
    int x = 0;
    return [=](std::size_t mode = 0) mutable -> void
           {
              switch(mode)
              {
                 case 1:
                    ++x;
                    std::cout << x << std::endl;
                    break;
                 case 2:
                    --x;
                    std::cout << x << std::endl;
                    break;
                 default:
                    std::cout << x << std::endl;
                    break;
              }
           };
 }
 
 int main()
 {
    auto f1 = func();
    auto f2 = func();
 
    f1(1); // 1
    f2(1); // 1
    
    f1(2); // 0
    f2(1); // 2
    
    f1(1); // 1
    f2(2); // 1
 
    f1(2); // 0
    f2(2); // 0
    
    f1(); // 0
    f2(); // 0
 }


処理を関数ごとに分ける場合、bind関数等は新しく関数を生成しているため、環境が共有されず使用できない。
処理を分ける場合は、上記のf1関数を生成した後、以下の処理を記述する。

 auto inc = [&]() { return f1(1); };
 auto dec = [&]() { return f1(2); };
 
 inc();
 dec();