8

値によってキャプチャされた値が const であるのに、参照によってキャプチャされたオブジェクトがそうでないのはなぜですか。

int a;

auto compile_error = [=]()
{
  a = 1;
}
auto compiles_ok = [&]()
{
  a = 1;
}

私にはこれは非論理的に思えますが、標準のように見えますか? 特に、キャプチャされた値の不要な変更は迷惑なバグである可能性がありますが、結果がラムダ スコープに限定される可能性が高いのに対し、参照によってキャプチャされたオブジェクトの不要な変更は、多くの場合、より深刻な影響につながります。

では、デフォルトで const 参照によってキャプチャしてみませんか? または、少なくとも [const &] と [&] をサポートしますか? このデザインの理由は何ですか?

回避策として、値によってキャプチャされた std::cref ラップされた const 参照を使用することになっているのでしょうか?

4

3 に答える 3

7

値によってポインタをキャプチャしているとしましょう。ポインター自体は const ですが、ポインターが指すオブジェクトへのアクセスは const ではありません。

int i = 0;
int* p = &i;
auto l = [=]{ ++*p; };
l();
std::cout << i << std::endl;  // outputs 1

このラムダは次と同等です。

struct lambda {
    int* p;
    lambda(int* p_) : p(p_) {}
    void operator()() const { ++*p; }
};

conston theは、次のように宣言するのと同等のoperator()()使用を行います。p

int* const p;

参照でも同様のことが起こります。参照自体は「const」ですが (参照を再配置できないため引用符で囲みます)、それが参照するオブジェクトへのアクセスはそうではありません。

于 2013-05-29T16:50:14.620 に答える
3

キャプチャされた参照const. むしろ、参照は常に暗黙的constです。言語には、参照が指す場所を変更できる構文はありません。a = 1;いつa参照されるかは、参照を変更するのではなく、参照が参照するものを変更することです。

「const 参照」について話すと、混乱すると思います。あなたは「const intへの参照」について話している(const int &)。そこにある「定数」は、参照自体ではなく、参照が指すものを指します。これはポインタに似ています。「const int へのポインタ」( const int *) では、ポインタ自体はそうではありませconstん。この型の変数に好きなだけ割り当てることができます。実際の「const ポインター」はint *const. ここでは、このタイプのものに割り当てることはできません。intただし、 it が指すものは変更できます。したがって、ポインターまたは参照の「const」は、それが指すものの「const」とは別のものです。「const intへのconstポインタ」を持つこともできます: const int *const.

于 2013-05-27T07:08:41.353 に答える
0

私の論理は次のように述べています。ラムダは単なるコードであり、オプションで必要な参照があります。実際に何かをコピーする必要がある場合 (通常は、shared_ptr のコピーなどのメモリ管理目的で発生します)、ラムダに独自の状態を持たせたくありません。それはかなり異常な状況です。

次の2つのオプションだけが「正しい」と感じると思います

  • いくつかのローカル変数を使用していくつかのコードを囲み、「それを渡す」ことができるようにします
  • 上記と同じように、メモリ管理のみを追加します。おそらく、そのコードを非同期で実行したいなどの理由で、作成スコープが消えてしまうからです。

しかし、ラムダが「変更可能」である場合、つまり const ではない値を取得する場合、これは実際には独自のstateをサポートしていることを意味します。つまり、 lambdaを呼び出すたびに、別の結果が得られる可能性があります。これは、実際の Closure に基づいているのではなく内部のstateに基づいています。関数型言語。

ただし、C++ は C++ であるため、その制限を回避する方法を提供します。これは、奇妙なことをしているという事実を確実に認識できるようにするためです。

これがあなたの理由になることを願っています。

于 2013-05-27T20:26:33.313 に答える