之前我有一个Q& A:Point of declaration in C++。规则声明点很好地适用于许多情况。现在,我混淆了auto
与此规则相结合的用法。
考虑这两个代码:
我。单独声明x
(我们不希望它起作用):
{
auto x = x;
}
II。通过外部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
。
II。如果声明点在=
之前:
auto object = expression;
^
嗯,这没有任何意义,因为auto
必须等到看到以下表达式。例如auto x;
无效。
更新:我需要一个答案,通过规则声明解释它。
答案 0 :(得分:19)
auto x = x; // inner x
是不正确的。
引用C ++ 11标准(强调我的):
7.1.6.4自动说明符
...
3 否则,变量的类型是从其初始化程序推导出来的。 声明的变量的名称 不应出现在初始化表达式中。 ...
因为x
之后=
解析为x
中的auto x
(如您所链接的问题中所述),上面的代码就是格式错误
答案 1 :(得分:10)
与任何其他类型的定义一样,x
的初始化设备右侧的auto 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.
}
答案 2 :(得分:4)
只需添加一个更明确的诊断示例:
auto ll = [&] { ll(); };
结果(gcc):
error: variable ‘auto ll’ with ‘auto’ type used in its own initializer
或(clang):
error: variable 'll' declared with 'auto' type cannot appear in its own initializer
auto ll = [&] { ll(); };
^
您可以看到有明确的规则。我没看过规格。
答案 3 :(得分:1)
编译器读取整个语句(从行的开头到下一个分号),然后使用操作优先级评估语句的不同部分,然后在{{1将被分配,即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
应该有用。