41

c++11で次のように記述する必要があるのはなぜですか。

[a,b]() mutable { a=7; } // b is needlessly mutable, potential source of bugs

それ以外の:

[mutable a,b]() { a=7; } // no problems here

これは見落としであり、十分に重要ではないと考えられていますか、それとも特定の技術的理由がありますか?

4

4 に答える 4

18

n2651にあなたの提案についての言及があります:

ラムダ式の構文を拡張して、クロージャーメンバーを可変として宣言する必要があるかどうかを宣言できるようにすることができます。

可変性はクロージャーオブジェクトのプロパティではなく、クロージャーに格納されている変数であるため、このアプローチはプログラマーを混乱させる可能性があります。

これが唯一の理由かどうかはわかりませんが、考えられたようです。ただし、ハーブサッターの提案mutableでは、キャプチャコピーを暗黙的に作成せずに削除することを提案しているconstため、再び変更が発生する可能性があります。

于 2012-12-27T04:23:55.213 に答える
6

おそらく、(右辺値の参照を使用できないのと同じように)ある種の見落としと、ラムダが概念的に実装される方法のアーティファクトです。

int   a;
int*  b;
float c;

auto lambda1 = [&a, b, c](int d) mutable -> void {};

class lambda1 {
public:
    void operator()(int d) {}
private:
    int&  a_;
    int*  b_;
    float c_;
};

auto lambda2 = [&a, b, c](int d) -> void {};

class lambda2 {
public:
    void operator()(int d) const {}
private:
    int&  a_;
    int*  b_;
    float c_;
};
于 2012-12-27T03:36:10.917 に答える
5

このmutableキーワードは、ラムダ式によって生成されたオブジェクトに適用され、個別にキャプチャされたアイテムには適用されないため、標準のセクション5.1.2、段落5で説明されているようconstに、メソッドの修飾子を使用してコンパイラーが実装できます。operator()

この関数呼び出し演算子は、lambdaexpressionのparameter-declaration-clauseの後にmutableが続かない場合にのみ、const(9.3.1)として宣言されます。

あなたの例では、ラムダ式によって生成されたクラスは次のようになります。

class lambda
{
  int a, b;

public:

  lambda( int a, int b ) : a( a ), b( b ) {}

  void operator()() // non-const due to mutable keyword
  {
    a = 7;
  }
};
于 2012-12-27T03:38:25.723 に答える
0

キーワードは、通常使用されるキーワードmutableのようには使用されません。この場合の反対を意味し、関数呼び出し演算子の定数に暗黙の関数オブジェクトを適用します。ただし、暗黙の関数オブジェクトの関数呼び出し演算子がデフォルトであるのに対し、通常はメンバー関数は非(「可変」)であるがデフォルトであることが意図されていました。ラムダ関数の導入は、コンテキストキーワード(および)の使用よりも前からあり、キーワードは。よりも優れた選択肢のようでした。mutableconstconstconstoverridefinalmutablenot const

于 2012-12-27T06:42:31.090 に答える