75240


以下のコードがコンパイルできないのは何故なんでしょうか？

[code]

    void f() {
        int x;
        +[x]{};
    }
    
[/code]

一見コンパイルできると思ったのですが、GCCでもClangでもMSVCでもコンパイルエラーでした。  
なお以下はコンパイルできるようです。

[code]

    void f() {
        +[]{};
    }
    
[/code]


CC BY-SA 4.0
2021-04-13T09:14:13.917
75238
2021-04-13T14:52:11.613
37855
question
c++
C++のラムダ関数がローカル変数をキャプチャするときに関数ポインタに変換できなくなるのはなぜ？


キャプチャする`int x`変数はスコープを抜けた時点で消去されます。しかし、ラムダ関数は別のスコープを持っています。 **キャプチャする**
と表現しているように、別の領域にコピーしていますし、それを破棄する処理も必要になります。つまり、ラムダ関数は関数の実行とは別にキャプチャしたオブジェクトの管理も必要になってきます。そうなると関数ポインターでは表現できなくなります。


CC BY-SA 4.0
2021-04-13T11:17:21.390
75240
2021-04-13T11:17:21.390
4236
75238
answer


> C++のラムダ関数がローカル変数をキャプチャするときに関数ポインタに変換できなくなるのはなぜ？

短い答え：C++実行環境において合理的な実装が不可能なためです。

* * *

思考実験として下記の関数`g`を考えます。関数`g`は「実行時に値が確定するローカル変数`x`を(コピー)キャプチャした関数ポインタ」を返す必要があります。

[code]

    auto g()
    {
      int x;
      std::cin >> x;
      // ラムダ式から関数ポインタへの変換に単項+演算子を利用
      return +[x]{};
    }
    
[/code]

この関数ポインタがさす先の実行可能コード（≒機械語命令列）はコンパイル時には生成不可能であり、プログラム実行時に実行可能コードを動的生成しなければなりません。また関数`g`が何度も呼び出されるシナリオでは異なる`x`値に応じた実行可能コードが必要となりますが、C++言語はガベージコレクタをもたないため実行可能コード片（≒動的に生成される関数）を破棄する契機がなくメモリを圧迫し続けます。


CC BY-SA 4.0
2021-04-13T14:52:11.613
75246
2021-04-13T14:52:11.613
49
75238
answer