web-dev-qa-db-ja.com

何もキャプチャしていないラムダはグローバル変数にアクセスできますか?

int n;    
int main()
{
    [](){ n = 0; }(); // clang says "ok"

    int m;
    [](){ m = 0; }(); // clang says "not ok"
}

私はただ疑問に思います:

ラムダが何もキャプチャしない場合、C++標準に従ってグローバル変数にアクセスできますか?

22
xmllmx

はい、そうです。通常の名前検索ルールが適用されます。

[expr.prim.lambda]/7 ...名前を検索する目的で...compound-statementlambda-expressionのコンテキストで考慮されます。

Re:ローカル変数がグローバル変数とは異なる方法で処理される理由。

[expr.prim.lambda]/1 ... iflambda-expressionまたは関数呼び出し演算子のインスタンス化一般的なラムダodr-uses(3.2)thisのテンプレートまたは到達範囲からの自動ストレージ期間を持つ変数、そのエンティティはlambda-expression

[expr.prim.lambda]/9 Alambda-expression最小の包含スコープはブロックスコープ(3.3.3 )はローカルラムダ式...です到達範囲ローカルラムダ式は、最も内側の囲み関数とそのパラメーターまでの囲みスコープのセットです。

あなたの例では、mはラムダの到達範囲からの自動ストレージ期間を持つ変数であり、そのためキャプチャされます。 nはそうではないので、そうである必要はありません。

17
Igor Tandetnik

実際、[](){ n = 10; }();は何もキャプチャしません。代わりにグローバル変数を使用します。

int n;    
int main()
{
    [](){ n = 10; }(); // clang says "ok"
    std::cout << n; // output 10
}

説明の capture-listを参照してください

capture-list-ゼロ以上のキャプチャのコンマ区切りリスト。オプションで、capture-defaultで始まります。

キャプチャリストは次のように渡すことができます(詳細な説明については以下を参照してください)。

  • [a、&b]ここで、aはコピーによってキャプチャされ、bは参照によってキャプチャされます。
  • [this]は、参照によって現在のオブジェクト(* this)をキャプチャします
  • [&]ラムダの本文で参照によって使用されているすべての自動変数と、存在する場合は参照によって現在のオブジェクトをキャプチャします
  • [=]ラムダの本体で使用されているすべての自動変数をコピーによってキャプチャし、存在する場合は参照によって現在のオブジェクトをキャプチャします
  • []何もキャプチャしません
9
Jiahao Cai

デフォルトでは、グローバル変数、静的変数、const変数にアクセスします。

#include <iostream>

int n;    
int main()
{
    [](){ n = 10; }();
    std::cout << n << std::endl;
    static int m = 1;
    [](){ m = 100; }();
    std::cout << m << std::endl;
    const int l = 200;
    [](){ std::cout << l << std::endl; }();
}
3
Soumya Kanti