72

C++ では、たとえば次のようにラムダを宣言できます。

int x = 5;
auto a = [=]() mutable { ++x; std::cout << x << '\n'; };
auto b = [&]()         { ++x; std::cout << x << '\n'; };

どちらも変更できますxが、違いは何ですか?

4

1 に答える 1

94

何が起こっている

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 を変更しないためです。

于 2013-06-05T16:15:08.847 に答える