C++ では、たとえば次のようにラムダを宣言できます。
int x = 5;
auto a = [=]() mutable { ++x; std::cout << x << '\n'; };
auto b = [&]() { ++x; std::cout << x << '\n'; };
どちらも変更できますx
が、違いは何ですか?
1 つ目は、自身のコピーのみを変更しx
、外部を変更しx
ないままにします。2 つ目は外側x
を変更します。
それぞれを試した後、print ステートメントを追加します。
a();
std::cout << x << "----\n";
b();
std::cout << x << '\n';
これは印刷されると予想されます:
6
5
----
6
6
そのラムダを考慮すると役立つ場合があります
[...] 式は、単純な関数オブジェクトを作成するための簡潔な方法を提供します
(標準の [expr.prim.lambda] を参照)
彼らは持っている
[...] public インライン関数呼び出し演算子 [...]
これはconst
メンバー関数として宣言されていますが、
[...] ラムダ式のparameter-declaration-clauseの後に次がない場合のみ
mutable
のように考えることができます。
int x = 5;
auto a = [=]() mutable { ++x; std::cout << x << '\n'; };
==>
int x = 5;
class __lambda_a {
int x;
public:
__lambda_a () : x($lookup-one-outer$::x) {}
inline void operator() { ++x; std::cout << x << '\n'; }
} a;
と
auto b = [&]() { ++x; std::cout << x << '\n'; };
==>
int x = 5;
class __lambda_b {
int &x;
public:
__lambda_b() : x($lookup-one-outer$::x) {}
inline void operator() const { ++x; std::cout << x << '\n'; }
// ^^^^^
} b;
Q:関数の場合const
、なぜ変更できるのx
ですか?
A:外側x
だけを変更しています。ラムダ自身x
は参照であり、操作は参照を++x
変更しませんが、参照された値を変更します。
これが機能するのは、C++ では、ポインター/参照の constness が、それを通して見える pointee/referencee の constness を変更しないためです。