Skip to content

Commit

Permalink
C++17 : 「ラムダ式での*thisのコピーキャプチャ」を追加 #416
Browse files Browse the repository at this point in the history
  • Loading branch information
faithandbrave committed Jul 25, 2017
1 parent 39947b9 commit 51d35e0
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 1 deletion.
1 change: 1 addition & 0 deletions lang/cpp11/lambda_expressions.md
Expand Up @@ -529,6 +529,7 @@ for_each(array, array + 4, <&>(double d) ( sum += factor ∗ d ));
- [C++11 ローカル型と無名型を、テンプレート引数として使用することを許可](local_and_unnamed_type_as_template_arguments.md)
- [C++14 ジェネリックラムダ](/lang/cpp14/generic_lambdas.md)
- [C++14 ラムダ式の初期化キャプチャ](/lang/cpp14/initialize_capture.md)
- [C++17 ラムダ式での`*this`のコピーキャプチャ](/lang/cpp17/lambda_capture_of_this_by_value.md)


## 参照
Expand Down
2 changes: 1 addition & 1 deletion lang/cpp17.md
Expand Up @@ -50,7 +50,7 @@ C++17では以下のTSが採用された:

| 言語機能 | 説明 |
|----------|------|
| ラムダ式での`*this`のコピーキャプチャ | キャプチャリストに`*this`を指定することで、`*this`をコピーキャプチャする |
| [ラムダ式での`*this`のコピーキャプチャ](cpp17/lambda_capture_of_this_by_value.md) | キャプチャリストに`*this`を指定することで、`*this`をコピーキャプチャする |
| `constexpr`ラムダ | ラムダ式の関数オブジェクトが定数式の文脈で使用された場合に、それがコンパイル時に評価されるようにする |


Expand Down
79 changes: 79 additions & 0 deletions lang/cpp17/lambda_capture_of_this_by_value.md
@@ -0,0 +1,79 @@
# ラムダ式での*thisのコピーキャプチャ
* cpp17[meta cpp]

## 概要
C++14までラムダ式で`[this]`のようにキャプチャをすると、`this`ポインタがコピーされていた。その場合、非同期処理のような状況で、ラムダ式の関数オブジェクトが呼び出されたときに、`this`ポインタが指すオブジェクトの寿命が付きている場合がある。

C++17では`[*this]`のようにキャプチャすることで、キャプチャ時点での`*this`オブジェクトをコピーできるようになった。

`[*this]`のキャプチャは、`[=, *this]`のようにデフォルトコピーキャプチャと併用できる。`[this, *this]`のようなキャプチャは指定できない。


## 備考
ラムダ式の関数オブジェクトが呼び出されたときに、`this`ポインタの寿命が付きる場合があることが正しい状況では、依然として[`std::weak_ptr`](/reference/memory/weak_ptr.md)のような機能を使用して、生死監視をする必要がある。


##
```cpp
#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;
}
```
* std::atomic[link /reference/atomic/atomic.md]
* is_finish.store[link /reference/atomic/atomic/store.md]
* is_finish.load()[link /reference/atomic/atomic/load.md]
* t.detach()[link /reference/thread/thread/detach.md]
## 出力
```
finished: 55
exit
```
## 関連項目
- [C++11 ラムダ式](/lang/cpp11/lambda_expressions.md)
## 参照
- [P0018R0 Lambda Capture of `*this` by Value](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0018r0.html)
- [P0018R1 Lambda Capture of `*this` by Value](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0018r1.html)
- [P0018R2 Lambda Capture of `*this` by Value](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0018r2.html)
- [P0018R3 Lambda Capture of `*this` by Value as `[=,*this]`](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0018r3.html)

0 comments on commit 51d35e0

Please sign in to comment.