このページはC++17に採用された言語機能の変更を解説しています。
のちのC++規格でさらに変更される場合があるため関連項目を参照してください。
概要
C++14までラムダ式で[this]
のようにキャプチャをすると、this
ポインタがコピーされていた。その場合、非同期処理のような状況で、ラムダ式の関数オブジェクトが呼び出されたときに、this
ポインタが指すオブジェクトの寿命が尽きている場合がある。
C++17では[*this]
のようにキャプチャすることで、キャプチャ時点での*this
オブジェクトをコピーできるようになった。
[*this]
のキャプチャは、[=, *this]
のようにデフォルトコピーキャプチャと併用できる。[this, *this]
のようなキャプチャは指定できない。
備考
[*this]
でコピーキャプチャしたオブジェクトは、デフォルトでconst
になるので注意。[this]
はポインタであるため書き換えができ、非const
メンバ関数を呼び出せる。しかし、[*this]
はオブジェクトをコピーしてconst
となるため、ラムダ式にmutable
を付けない限り、非const
メンバ関数を呼び出せない。- ラムダ式の関数オブジェクトが呼び出されたときに、
this
ポインタの寿命が尽きる場合があることが正しい状況では、依然としてstd::weak_ptr
のような機能を使用して、生死監視をする必要がある。
例
#include <iostream>
#include <thread>
#include <atomic>
std::atomic<bool> is_finish;
struct F {
void start()
{
auto proc = [*this]() mutable {
// てきとうな時間のかかる処理として、[1, 10]の合計値を計算
int sum = 0;
for (int i = 1; i <= 10; ++i) {
sum += i;
}
// 処理が終了したらクラス内のメンバ関数を呼び出す。
// この段階で*thisが有効でなければならない
onFinish(sum);
};
// バックグラウンドスレッドでproc関数オブジェクトを実行する
std::thread t(proc);
t.detach();
}
void onFinish(int sum)
{
std::cout << "finished: " << sum << std::endl;
is_finish.store(true);
}
};
int main()
{
F().start();
while (!is_finish.load()) {}
std::cout << "exit" << std::endl;
}
出力
finished: 55
exit