正如预期的那样,以下内容在 C++11 中失败,因为该语言没有 bog 标准函数的返回类型推导:
auto main()
{
return 0;
}
但是,C++14 确实如此,所以我无法解释以下错误(在 GCC trunk、clang 3.8 和 Visual Studio 2015 中具有相同的结果):
error: 'main' must return 'int'
标准中是否有一段我没有看到的内容,禁止
main
的返回类型扣除?或者两个编译器都不兼容?
(无论它的价值,我从来没有真正这样做过。
int main()
为了胜利......)
阅读 C++17 草案 §3.6.1/2:
...并且它应具有
类型的声明返回类型,...int
所以是的,我会说禁止使用扣除。
与最后一个 C++14 草案中的措辞几乎完全相同(与 C++17 草案相同的部分):
它应该有一个声明的返回类型,类型为在阅读评论和其他答案后,
int
,...
return
语句之前并不知道返回类型。可能会返回其他类型(可隐式转换为 int
),这也会导致推导的类型错误,这种情况也并不罕见。预先声明返回类型(通过正常的老式方式,或使用尾随返回类型)将在声明函数时设置类型,并且可以由编译器立即检查是否正确。
至于允许类型别名,它们只是类型的别名。所以允许例如
typedef int my_type;
my_type main() { ... }
与
真的没有什么不同
int main() { ... }
从3.6.1/2(强调我的):
[...]它应具有
int
类型的而没有尾随返回类型时,函数的声明的返回类型,但除此之外,其类型是实现定义的。
当使用auto
声明的返回类型
仍然是
auto
,即使推导的返回类型可以是其他类型。标准中没有明确说明declared 和 deduced 之间的区别,但 7.1.6.4/7 可能会提供一些启示: 当 [...]
return
语句出现在使用包含占位符类型的返回类型声明的函数中时,推导的返回类型 [...] 由其初始值设定项的类型确定。如果
return
没有操作数或具有类型为void
的操作数,则声明的返回类型应为auto
,推导的返回类型为void
。我的理解是:
auto main(){ return 0; }
声明的返回类型仍然是
auto
,尽管推导的返回类型
将是
int
。根据上面的 3.6.1/2,main
的声明的返回类型必须
为
int
。因此,这是不正确的。
但是,尾随返回类型被视为声明的返回类型。从 7.1.6.4/2 开始:
如果函数声明符包含
trailing-return-type(8.3.5),则trailing-return-type 指定函数声明的返回类型。
$ cat a.cpp auto main() -> int {} $ g++ -Wall -std=c++14 a.cpp $
C++14 和 C++17 中的所有引号都是相同的。
从 3.6.1 [basic.start.main]开始
1 程序应包含一个名为 main 的全局函数,它是 指定程序的开始....
2 实施不得 预定义主要功能。该函数不得超载。它 应具有 int 类型的声明返回类型,但除此之外其类型 是实现定义的...
如果标准是限制推导,那么我认为“声明返回类型 int”就是这样的说法。
许多答案都很好地提到了标准中的引用。但是
根据 C++ 标准 (somewhere),
return
语句在 main()
内不是强制的。 Bjarne Stroustrup 的网站
中明确提到了这一点:在 C++ 中,
main()
不需要包含显式的
return
语句。此时返回的值为0
,表示执行成功。这意味着以下声明是有效的:
auto main () {}
可以假设在
return 0;
之前有一个隐式的 }
语句。所以在这种情况下
auto
被解释为
int
。然而,从 C++14 的技术细节来看,由于没有 return 语句,因此 auto
必须推导为
void
!那么,“int
vs
void
”,要考虑什么?
IMO 这是一个警告,它也阻止
auto
作为逻辑意义上的返回类型。正如各种评论中所讨论的,我确实在标准中遗漏了它,因为我认为是 C++14 FDIS 的副本实际上不是这样的东西(而是一个稍旧的草案),并且这个词“声明”被偷偷塞进了