1. ホーム
  2. c++

[解決済み] ラムダで参照渡し('&this')を捕捉できないのはなぜですか?

2023-01-14 06:55:39

質問

正しいキャプチャ方法は this (オブジェクトのプロパティを変更する)ラムダでの正しい方法は以下の通りです。

auto f = [this] () { /* ... */ };

しかし、私が見た次のような特殊性が気になる。

class C {
    public:
        void foo() {
            // auto f = [] () { // this not captured
            auto f = [&] () { // why does this work?
            // auto f = [&this] () { // Expected ',' before 'this'
            // auto f = [this] () { // works as expected
                x = 5;
            };
            f();
        }

    private:
        int x;
};

私が混乱している(そして答えて欲しい)奇妙な点は、なぜ次のように動作するのかということです。

auto f = [&] () { /* ... */ }; // capture everything by reference

そして、なぜ明示的にキャプチャできないかというと this を参照によって捕捉することができない理由です。

auto f = [&this] () { /* ... */ }; // a compiler error as seen above.

どのように解決するのですか?

原因 [&this] が動作しないのは、構文エラーだからです。 カンマで区切られた各パラメータが lambda-introducercapture :

capture:
    identifier
    & identifier
    this

を見ればわかるように &this は構文上許されないことがわかります。 なぜ許されないかというと、あなたは決して this は小さな定数ポインタなので、参照で捕捉することはできません。 値で渡したいだけなのです。ですから、この言語は this を参照で捕捉することをサポートしていません。

捕捉するために this を明示的に捕捉するには [this] として lambda-introducer .

最初の capturecapture-default というものである。

capture-default:
    &
    =

これは、何を使っても自動的にキャプチャされることを意味し、参照によって ( & ) または値によって ( = ) それぞれで、しかし this の扱いは特別で、どちらの場合も前に述べた理由で値で捕捉されます (デフォルトの捕捉が & であっても、通常は参照による捕捉を意味します)。

5.1.2.7/8:

名前検索(3.4)の目的のために,型と値を決定して this (9.3.2) の型と値を決定し、非静的なクラス・メンバーを参照する id- を使用して、非静的クラスメンバを参照するクラスメンバアクセス式に変換します。 (*this) (9.3.1), 複合文[OF THE LAMBDA]は,ラムダ式の文脈で考慮される。

つまり、ラムダはメンバ名を使用するとき、囲むメンバ関数の一部であるかのように動作します(例では、名前 x の暗黙の用法"を生成します。 this を生成します。

ラムダキャプチャーがキャプチャーのデフォルトを含んでいる場合 & である場合、ラムダ・キャプチャー内の識別子は の前に & . ラムダキャプチャーにキャプチャーのデフォルトが含まれている場合、そのデフォルトは = である場合、そのラムダキャプチャには this を含まないものとし,含む各識別子の前に & . 識別子または this は、ラムダ捕捉の中に複数回出現してはならない。 はラムダキャプチャーに複数回出現してはならない。

なので [this] , [&] , [=] または [&,this] として lambda-introducer を捕捉するために this のポインタを値で捕捉します。

しかし [&this][=, this] は不正な形式です。 最後の場合、gccは寛容に [=,this] に対して警告します。 explicit by-copy capture of ‘this’ redundant with by-copy capture default というように、エラーではなく