実現したいこと/試したこと
最終的に実現したいことを端的に述べますと、ローカル変数を参照する特定の処理を定義だけしておき、あとから実行したいということになります。
そこで、まず、下記のようなソースコードを考えました。
C++
1#include <functional> 2#include <iostream> 3class Foo { 4public: 5 std::function<void()> f; 6 void func() { 7 int i = 1; 8 std::cout << "func: " << i << ", " << &i << std::endl; 9 f = [=]()->void { // 参照キャプチャ`&`不可:解放済み変数にアクセスしておかしな値が出力される 10 std::cout << "lambda: " << i << ", " << &i << std::endl; 11 }; 12 i = 2; 13 } 14}; 15int main() { 16 Foo foo; 17 foo.func(); 18 foo.f(); 19 return 0; 20}
上記プログラムの実行結果は下記のようになります。
func: 1, 0x70fd9c lambda: 1, 0xbf23f0
ポイントは、ラムダ式によって出力された変数の値が2ではなく、1であるということです。
このことから、ラムダ式のコピーキャプチャはラムダ式が定義される直前の値がコピーされる仕様であると理解しました。
しかしながら、下記のソースコードを考えたときにわからなくなりました。
C++
1#include <functional> 2#include <iostream> 3class Foo { 4private: 5 int i; 6public: 7 std::function<void()> f; 8 void func() { 9 i = 1; 10 std::cout << "func: " << i << ", " << &i << std::endl; 11 f = [=]()->void { // 参照キャプチャ`&`可能 12 std::cout << "lambda: " << i << ", " << &i << std::endl; 13 }; 14 i = 2; 15 } 16}; 17int main() { 18 Foo foo; 19 foo.func(); 20 foo.f(); 21 return 0; 22}
変更点は、ローカル変数をメンバ変数に変更しただけです。
しかしながら、上記プログラムの実行結果は下記のようになります。
func: 1, 0x70fde0 lambda: 2, 0x70fde0
ラムダ式によって出力された変数の値が2になっています。
ラムダ式が定義されたあとに実行した値の変更がなぜか反映されてしまっています。
一体ラムダ式のコピーキャプチャはどのタイミングで実行される仕様なのでしょうか?
そもそも、一番最初のソースコード自体が未定義動作の代物なのでしょうか?
いくつかのコンパイラで試しましたが、動作が一貫していたので、C++の言語仕様に規定されていると考えていたのですが…
言語仕様のこのあたりに記載があるよ等も教えていただけると私の勉強にもなり助かります。
回答よろしくお願いします。
補足情報(FW/ツールのバージョンなど)
C++17

回答2件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2023/10/25 14:26
2023/10/25 14:58
2023/10/26 16:54