【发布时间】:2012-06-26 21:25:15
【问题描述】:
根据 C++11 标准,以下程序是否是格式良好且可移植的 C++?
int main(int argc, char const* const* argv) {}
【问题讨论】:
根据 C++11 标准,以下程序是否是格式良好且可移植的 C++?
int main(int argc, char const* const* argv) {}
【问题讨论】:
没有。在纯可移植 C++ 程序中,argv 参数(如果存在)没有 const 修饰符。
编辑:参见 C++11 草案标准的第 3.6.1.2 节,其中(在我之前的版本中)指出:
实现不应预定义主要功能。这个功能 不得超载。它应该有一个 int 类型的返回类型,但是 否则它的类型是实现定义的。所有实现 应允许以下两个 main 定义:
int main(){ /*...*/ }和
int main(int argc, char* argv[]) { /* ... */ }
【讨论】:
取决于您所说的便携式。一个邪恶的 C++ 实现可能会拒绝它,理由是它的签名 int(int,char const*const*) 不同于所需的允许签名之一 int() 和 int(int,char**)。 (一个邪恶的实现似乎会拒绝auto main(int argc,char* argv[]) -> int,或者实际上拒绝任何main 的定义,其中body 不是{ /* ... */ })
但这不是典型的。我不知道添加 const 会导致调用 main 的问题的任何实现,并且由于 C++11 添加了有关“类似”类型的位,因此在访问 char** 时不会违反严格的别名规则对象通过char const * const * 变量。
因此,虽然符合规范的实现在技术上可能会拒绝它,但我认为它可以移植到您可能希望使用的任何实现中。
【讨论】:
const 添加到形式参数会影响名称修改。这适用于main 的原因是因为main 通常免于重载(因为无论如何您都不允许重载main)。添加类似类型仅意味着当您将char** 作为char const * const * 访问时,您不会因为违反严格的别名规则而自动获得未定义的行为。在我知道的所有实现上,它在 C++11 之前运行良好,但在技术上它是 UB。现在不应该是UB
auto main(int argc,char* argv[]) -> int 的来源或标准引用是不同的签名?那么int main(int argc, char** argv) 不也是一个不同的签名吗?
main 的这两个定义 是允许的。它没有说这两个参数列表或这两个签名,这就是为什么你甚至可以开玩笑地争论(就像 bames53 所做的那样)body 必须是/* ... */。但是,上一句谈到了 main 的 type,而声明为 auto main(int, char**) -> int 的函数的类型与给出的示例之一的类型相同。我想说的是,在对标准的合理解读中,任何与任一示例具有相同签名的 main 都可以。
extern "C"。然后在另一个 TU 中错误地声明任何函数,并在定义 char const *const 时使用带有 char ** 的原型调用它,这与使用 main 的可能性一样。不过我不建议这样做,我认为如果你想要 const-qualified argv 做“正确”的事情就是写 int main(int argc, char **argv) { return my_main(argc, argv); } 并用 const 定义 my_main。进行转换,即使类似的类型实际上不需要。