8

私は現在 c++11 ラムダで遊んでいて、理解できない例を見つけました。標準によると:

最小のエンクロージング スコープがブロック スコープ (3.3.3) であるラムダ式は、ローカル ラムダ式です。他のラムダ式は、そのラムダイントロデューサにキャプチャ リストを持ってはなりません

だから、私は簡単な例を作成しました:

int a = 10;
auto x  = [a] { return 1;};
int main() {
    int k = 5;
    auto p = [k]{ return k; };
    return 0;
}

ideone のコード: http://ideone.com/t9emu5

非ブロックスコープで変数をキャプチャするため、このコードはコンパイルされないことを期待していました(または、少なくとも auto x = ... 部分がブロックスコープにないと考えています)。しかし、コードはコンパイル中です - 大丈夫ですか?

大丈夫ですか - ブロックスコープは何ですか?

(現在、ideone サイトにしかアクセスできないため、使用しているコンパイラのバージョンはわかりません。

説明してくれてありがとう!

4

1 に答える 1

12

これはコンパイラの拡張機能のようです。g++4.8.1 は、警告を出しながらこれをコンパイルします:

警告: 非自動保存期間での変数 'a' のキャプチャ [デフォルトで有効]

clang++3.4 はこれをコンパイルしません:

エラー: 自動保存期間がないため、'a' をキャプチャできません

どちらも [expr.prim.lambda]/10 を参照します。

キャプチャ リスト内の識別子は、非修飾名検索の通常の規則 (3.4.1) を使用して検索されます。そのような各ルックアップは、ローカルラムダ式の到達スコープで宣言された自動ストレージ期間を持つ変数を見つけます。

ラムダの囲みスコープを追加でチェックしていないようです。冗長であると想像できます(非ブロック/名前空間スコープで自動保存期間を持つ変数の名前はありません)。


ブロック スコープは [basic.scope.block]/1 で定義されます。

ブロック (6.3) で宣言された名前は、そのブロックに対してローカルです。ブロックスコープがあります。

ブロックは次のように定義されます。

必要な場所で複数のステートメントを使用できるように、複合ステートメント (「ブロック」とも呼ばれます) が用意されています。

     複合文:
         { statement-seq opt }

したがって、グローバルに宣言されたラムダがブロックスコープにないことは正しいです。

于 2013-10-13T12:15:06.967 に答える