【问题标题】:"Variable shadowed" warning in lambda (when not captured)lambda 中的“变量阴影”警告(未捕获时)
【发布时间】:2021-02-28 00:21:40
【问题描述】:

让我们考虑一下这段代码:

int main()
{
    int a = 1;

    auto f1 = [a]() {
        int a = 10;
        return a;
    };

    auto f2 = []() {
        int a = 100;
        return a;
    };

    return a + f1() + f2();
}

当使用标志 -Wshadow 和 gcc(在 10.2 上测试)时,我们会收到以下警告:

<source>:26:13: warning: declaration of 'a' shadows a lambda capture [-Wshadow]
    6 |         int a = 10;

<source>:21:13: warning: declaration of 'a' shadows a previous local [-Wshadow]
   11 |         int a = 100;

我理解第一种情况,我们显式捕获a,因此隐藏了原始本地。然而,第二种情况很有趣,因为如果我们删除声明 int a = 100;,我们会得到一个编译错误 (= error: 'a' is not captured: return a;)。这不是“证明”声明与原始本地声明不在同一范围内,因此我们实际上并没有隐藏任何东西吗?因此我的问题是,警告(对于第二种情况)是否确实有效,或者 gcc 是否在这里有点过于严格?

【问题讨论】:

  • 省略int a = 100; 行时会出现什么编译器错误?
  • 我认为这是一个编译器错误 - clang does not report it
  • @PaulSanders Clang 确实会报告 f2 的警告,但如果您提供 -Wshadow-all 选项。
  • @heapunderrun 对不起,我的错。当我从 gcc 切换到 clang 时,Wandbox 清除了编译器选项。

标签: c++ gcc lambda compiler-warnings


【解决方案1】:

你是对的,lambda a 不会影响 main::a,因为 main::a 没有在 lambda 中捕获,因此不在范围内。

不过我想想影子警告的目的是什么:避免程序员混淆。如果程序员看到了外部声明但没有看到内部声明的长代码体,他或她可能会错误地假设内部变量的使用是指外部变量。这种可能的混淆在这里仍然适用,即使该变量在技术上并未影响外部变量。

我不知道这是警告的意图还是错误。或者即使这是一个足够令人信服的理由,甚至可以发出警告,甚至是措辞不同的警告。无论如何,阴影警告都是有问题的。您可以找到很多关于影子警告的讨论和错误报告,即使技术上正确也被认为是有害的。

【讨论】:

  • 至于“您可以找到很多关于影子警告的讨论和错误报告,即使技术上正确也被认为是有害的”,您介意详细说明吗?
【解决方案2】:

这不是“证明”声明与原始本地声明不在同一范围内,因此我们实际上没有隐藏任何东西吗?

没错。外部a 不在范围内。您在第二个示例中的声明不会影响任何内容。

因此我的问题是,警告(对于第二种情况)是否确实有效,或者 gcc 是否在这里有点过于严格?

第二个警告中没有什么值得关注的,除了如果您将变量命名为比 a 更具表现力的名称,可能不会发生错误的阴影。

【讨论】:

  • gcc 也不一致,如果您将其设为 a little functor 而不是 lambda,则不会发出警告
猜你喜欢
  • 2019-07-06
  • 2019-04-05
  • 2017-12-04
  • 1970-01-01
  • 1970-01-01
  • 2023-03-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多