- cpp14[meta cpp]
「初期化キャプチャ(init-capture)」は、任意の式の結果をラムダ式にキャプチャする機能である。
int increment(int x)
{
return x + 1;
}
int main()
{
// increment(3)の戻り値を、変数aとしてラムダ式内で使用する
auto f = [a = increment(3)](int b) { return a + b; };
int result = f(2); // result == 6
}
この機能を使用することで、以下のようなこともできる:
-
変数をムーブによってキャプチャする
std::vector<T> v; // 巨大な配列 auto f = [x = std::move(v)] { /* … */ };
- std::move[link /reference/utility/move.md]
-
ひとつの変数に対して、コピーキャプチャと参照キャプチャを同時に行う
int a = 3; auto f = [b = a, &c = a] { // このラムダ式内で、変数bはaのコピー、変数cはaへの参照 };
「初期化キャプチャ(init-capture)」が追加されたことにより、従来の変数名もしくはthis
を指定するキャプチャは「簡易キャプチャ(simple-capture)」と呼ばれることとなった。
初期化キャプチャの構文は以下:
identifier initializer
& identifier initializer
1行目は、初期化式の結果を、任意の識別子で受け取る構文。
2行目は、初期化式の結果への参照を、任意の識別子で受け取る構文。
int x = 3;
std::vector<int> v = {1, 2, 3};
auto f = [a = x + 1, // 式x + 1の結果を変数名aとして、ラムダ式内で使用する
&b = x, // 変数xへの参照を変数名bとして、ラムダ式内で使用する
c {std::move(v)}] {}; // 波カッコによる初期化構文を使用して、変数vを変数cにムーブする
- std::move[link /reference/utility/move.md]
初期化キャプチャの初期化式は、ラムダ式を定義した時点で評価される。
初期化キャプチャでは、パラメータパックのキャプチャはできない。
#include <memory>
#include <utility>
int main()
{
std::unique_ptr<int> p = std::make_unique<int>(3);
// pの所有権を、ラムダ式内の変数qに移動させる
// unique_ptrは、ムーブはできるがコピーはできない型だが、
// そのためにpを参照キャプチャすると、寿命が切れたpに不正アクセスしてしまう
// 可能性がある。
auto f = [q = std::move(p)] {};
}
- std::make_unique[link /reference/memory/make_unique.md]
- std::move[link /reference/utility/move.md]
出力 :
#include <iostream>
#include <utility>
#include <thread>
#include <future>
int main()
{
std::promise<int> p;
std::future<int> f = p.get_future();
// 時間のかかる処理用のスレッドに、
// 処理結果を書き込むためのpromiseオブジェクトを移動させる。
//
// 処理結果を書き込むスレッドにはpromiseオブジェクトの所有権を持たせ、
// 処理結果を読み込むスレッドにはfutureオブジェクトの所有権を持たせる。
std::thread t {[x = std::move(p)]() mutable {
// …時間のかかる処理…
// 処理の結果を書き込む
x.set_value(3);
}};
// 別スレッドでの処理結果を読み込む
int result = f.get();
std::cout << result << std::endl;
t.join();
}
- std::promise[link /reference/future/promise.md]
- p.get_future()[link /reference/future/promise/get_future.md]
- std::future[link /reference/future/future.md]
- std::move[link /reference/utility/move.md]
- x.set_value[link /reference/future/promise/set_value.md]
- f.get()[link /reference/future/future/get.md]
出力 :
3