【问题标题】:Point of declaration for auto keywordauto 关键字的声明点
【发布时间】:2013-10-02 09:05:37
【问题描述】:

我之前有一个问答:Point of declaration in C++point-of-declaration 规则很好地适用于许多情况。现在,我对结合这条规则使用auto 感到困惑。

考虑这两个代码:

我。自己声明 x(我们不希望它起作用)

{
  auto x = x;
}

二。用外部x 声明内部x (在gcc 4.8.x 中出错)

{
  int x = 101; // the outer x
  {
    auto x = x; // the inner x
  }
}

根据声明点规则,它应该可以工作,但不能。似乎标准中还有一条我错过了的规则。问题是,使用auto时的声明点在哪里?

 

有两种可能:

我。如果声明点在=之后,则在语句末尾:

auto object = expression;
                        ^
                        Is it here? If it is, why gcc complains?

所以第二个声明是有效的并且必须有效,因为没有x 而是那个外部声明(之前声明过)。因此auto x=x 是有效的,内部的x 应该分配给101

 

二。如果声明点在=之前:

auto object = expression;
           ^

好吧,这没有任何意义,因为auto 必须等到看到下面的表达式。例如auto x; 无效。


更新:我需要一个通过规则声明点解释它的答案。

【问题讨论】:

  • auto x = x 失败,因为x 解析为本地x(即auto x),但尚未推断出x 的类型。就像int y = y 中的y 解析为int y 一样。
  • @Simple:我的问题是,为什么它会解析到本地。
  • @Simple:跟随问题thisauto x=xx 已经定义时应该可以工作。
  • 我不知道问题出在哪里。 xauto x 之后的范围内,但它还没有已知类型;尝试使用 x 作为初始化程序会导致错误,因为 x 还没有类型。
  • @MM。 “所以内部范围内没有x”是错误的。仅仅因为它还没有类型并不意味着它不存在。

标签: c++ c++11


【解决方案1】:
auto x = x; // inner x

格式不正确。

引用 C++11 标准(重点是我的):

7.1.6.4 自动说明符

...

3 否则,变量的类型是从它的初始化器推导出来的。 被声明的变量名 不应出现在初始化表达式中。 ...

因此,因为= 之后的x 解析为auto x 中的x(如您链接的问题中所述),所以上面的代码格式不正确。

【讨论】:

  • 啊,很高兴看到标准有远见,不仅将其留给其他规则的副产品。
  • 我最近在一个跨平台项目中注意到,Microsoft Visual C++ 编译器 (MSVC 2017) 允许内部“auto x(x)”声明并使用外部 x 的值。 (根本没有警告)。但是,“auto x = x”会产生警告和未定义的 x。
【解决方案2】:

就像在任何其他类型的定义中一样,auto x = x 的初始化程序右侧的 x 解析为本地 auto x。 C++ 一直这样做(即int x = x 编译但会给你未定义的行为)。

auto x = x 无法编译的原因是,当 x 在作用域内时,它还没有已知类型,因此将其用作初始化程序失败,因为无法从表达式中推断出类型。

就像任何其他类型的声明一样,x 在其声明符 auto x 之后的范围内。

int x = 10;
int y = 20;
{
    int x = x;  // This is NOT the outer x. This is undefined behaviour (reading an
                // uninitialised variable).
    auto y = y; // This is NOT the outer y. This is a compile error because the type of
                // y is not known.
}

【讨论】:

    【解决方案3】:

    只需添加一个具有更明确诊断的示例:

    auto ll = [&] { ll(); };
    

    结果(gcc):

    error: variable ‘auto ll’ with ‘auto’ type used in its own initializer
    

    或(叮当声):

    error: variable 'll' declared with 'auto' type cannot appear in its own initializer
        auto ll = [&] { ll(); };
                        ^
    

    您可以看到对此有明确的规则。我没有看过规格。

    【讨论】:

      【解决方案4】:

      编译器读取整个语句(从行首到下一个分号),然后使用操作的优先级评估语句的不同部分,然后当auto x的值到达时将被分配,在= 符号之后出现的类型被占用。

      例如:

      template <typename T>
      T sum(T a, T b)
      {
          return a+b;
      }
      
      int main()
      {
          auto x = sum<double>(1,5); // x here is a double, because the return value is double
          auto y = sum<int>(1,7); //y is an int, because the return value is int
      }
      

      关于您的auto x = x,您正在重新定义相同的变量名称。那是无效的! auto y = x 应该可以工作。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-10-08
        • 2013-02-25
        • 2017-09-06
        • 1970-01-01
        相关资源
        最近更新 更多