int main(int, char const* const*)是否格式良好?

7
根据C++11标准,下面的程序是符合规范且可移植的C++程序吗?
int main(int argc, char const* const* argv) {}
2个回答

12

在一个纯粹的可移植C++程序中,如果存在argv参数,则它没有const修饰符。

编辑: 参见C++11草案标准的3.6.1.2节,该节(在我手边的版本中)规定:

  

实现不得预定义main函数。此函数不得重载。它必须返回int类型,但其他类型是由实现定义的。所有实现都应允许以下两个main定义:

  

int main(){ /*...*/ }

  

  

int main(int argc, char* argv[]) { /* ... */ }


3
取决于您对“可移植”的定义。一个邪恶的C++实现可以拒绝它,称其签名为,与所需允许签名之一和不同。(邪恶实现似乎可以拒绝auto main(int argc,char* argv[]) -> int或者任何定义main且主体不是{ /* ... */ }的情况)
然而,这并不是典型的情况。我不知道有哪些实现会因添加const而在调用main时出现问题,由于C++11添加了关于“类似”类型的部分,因此在通过char const * const *变量访问char**对象时,不会违反严格别名规则。
因此,虽然符合规范的实现理论上可能会拒绝它,但我认为它会在您可能想要使用的任何实现中保持可移植性。

天啊,我没有意识到将类似类型添加到法定别名中是为了使提供的参数和形式参数类型不匹配的函数能够正常工作;-) 但是,是的,它可能只是起作用(TM)。 - Steve Jessop
@SteveJessop 这并不是旨在实现这一点的,事实上通常情况下也不会实现这一点,因为将 const 添加到形式参数中会影响名称重载。之所以对于 main 起作用是因为 main 通常免于重载(因为你无论如何都不能重载 main)。添加类似类型只意味着当你将 char ** 访问为 char const * const * 时,你不会自动违反严格别名规则而导致未定义行为。在 C++11 之前,我知道所有实现都可以正常工作,但从技术上讲,它是未定义的行为。现在它不应该是未定义的行为了。 - bames53
3
你是否有关于auto main(int argc, char* argv[]) -> int是不同签名的来源或标准引用?int main(int argc, char** argv)难道也不是一个不同的签名吗? - Cactus Golov
@AntonGolov:我认为这里的标准措辞非常模糊。它只是说允许这两种main定义。它没有说这两个参数列表或这两个签名,这就是为什么你甚至可以诙谐地争论(正如bames53所做的那样),主体必须是“/.../”。 但是,前面的句子谈到了 main 的类型,而声明为auto main(int,char **)->int的函数的类型与给出的示例之一的类型相同。我认为在标准的合理阅读中,任何具有与任一示例相同签名的main都是可以的。 - Steve Jessop
@bames53:我只是开玩笑,但如果名称混淆是唯一的障碍,那么您可以始终使用extern "C"。然后在另一个TU中错误地声明任何函数,并在使用char **原型调用它时,当它被定义为char const *const时,与使用main的这个东西一样可能会起作用。虽然我不建议这样做,但我认为如果您想要const限定的argv,则“正确”的做法就是编写int main(int argc, char **argv) { return my_main(argc, argv); }并使用const定义my_main。进行转换,即使类似的类型实际上不需要转换。 - Steve Jessop

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接