【问题标题】:Are nested range-based for statements strictly legal?嵌套的基于范围的语句是否严格合法?
【发布时间】:2014-01-29 00:50:16
【问题描述】:

考虑这段代码:

#include <vector>
#include <iostream>

int main()
{
    std::vector<int> v1 {1,2};
    std::vector<int> v2 {4,5};
    for (auto i : v1) {
       for (auto j : v2) {
          std::cout << i << ',' << j << '\n';
       }
    }
}

正如所料,GCC 4.8 compiles it just fine,输出为:

1,4
1,5
2,4
2,5

但是,C++11 定义了 ranged-for:

{
   auto && __range = range-init;
   for ( auto __begin = begin-expr,
              __end = end-expr;
        __begin != __end;
        ++__begin ) {
     for-range-declaration = *__begin;
     statement
   }
}

确实说:

__range__begin__end 是仅为说明定义的变量

但它没有明确说明每个 ranged-for 语句应该扩展为其中每个变量都是唯一的代码,因此不会在封闭的 ranged-for 中隐藏相同的变量。

为此,在我看来,嵌套的 ranged-for 语句不能保证按预期工作。

我们确定这不是缺陷吗?

【问题讨论】:

  • 您是否建议内循环可能无法工作,因为可能存在相同的说明性变量名称?
  • 嗯,这种感觉就像问一个非问题,然后自己回答来捞分……
  • @Sean:自我回答不是“钓鱼积分”。捐赠时间和精力来帮助其他人学习我所学到的东西。如果您认为这不是问题,欢迎您投反对票,但我鼓励您首先检查 language-lawyer 标记的用途。
  • 我完全支持人们捐赠时间并分享他们所学到的东西。我只是惊讶于您的声誉得分,您认为您只是刚刚了解到这不是一个问题。毕竟,我们已经嵌套了 forifwhile 语句有一段时间了!
  • @Sean:具体来说,它是关于 ranged-for 的定义,以及该定义在标准中的呈现方式。和ifwhile 一点关系都没有。

标签: c++ c++11 language-lawyer


【解决方案1】:

是的,这是完全合法的。

ranged-for 的整个定义尽管在标准中以代码形式给出几乎是唯一的,但并不是简单的扩展:此结构旨在使用所有操作的中间表示在编译器内部进行扩展必填。

简而言之,使用“展示”一词意味着无论如何这都是有效的伪代码。

此外,如果您仔细查看这些变量的范围,它们不可能与在封闭的 ranged-for 语句中声明的指定用法相同的变量发生冲突,我们自己的statement无论如何都无法访问它们。也就是说,任何隐藏这些循环变量都不会导致意外行为的情况。

【讨论】:

  • 这不就是“仅展示”的意思吗? :)
  • @jrok 如果他们暴露了不同的东西。关键不是“仅展示”位,而是整个构造周围的{}
  • @R.MartinhoFernandes:这将解决任何潜在的“重新声明”错误(对吗?我忘记了块作用域在这方面是如何工作的),但它不能解决潜在的名称隐藏问题。
  • 同意第二个注释,即使您使用相同的变量天真地扩展循环,您仍然会得到正确的行为。
  • @LightnessRacesinOrbit 我认为隐藏名称在这里不是问题,内部的 for-each 块(我们可能在其中访问变量,因此它也可能是三分之一的第二个)将隐藏在更外部的名称中声明的名称,正确的行为 IMO。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多