为啥 C++ 中的 main() 没有重载以使用 std::string?

Posted

技术标签:

【中文标题】为啥 C++ 中的 main() 没有重载以使用 std::string?【英文标题】:Why main() in C++ is not overloaded to use std::string?为什么 C++ 中的 main() 没有重载以使用 std::string? 【发布时间】:2012-08-17 20:17:48 【问题描述】:

我试图创建一个程序,该程序使用main() 函数参数通过命令行获取参数。作为一个(基本的)C++ 程序员(即使我非常了解 C 风格的指针和数组),我几乎从未使用过 char* 字符串和 C 数组。我花了一些时间来获取main() 参数并将其转换为std::string... 所以问自己:为什么在C++ 中main() 函数没有重载以采用std::vector<std::string> argv 而不是旧的char* argv[]

对于“重载”,我指的是main() 函数如int main()int main(int argc, char *argv[]) 的共存,而不是程序员编写的普通函数的重载。

【问题讨论】:

将东西填充到字符串向量中非常简单,但从字符串向量创建 char* argv[] 则不然。 @PlasmaHH 是的。为什么编译器不能添加此重载所需的单个 ctor 调用? @DavidRodríguez-dribeas 我知道main()不能被用户超载。我的意思是语言上的“过载”。我们已经有两个标准版本的 main。 这是***.com/questions/6408183/is-main-overloaded-in-c 的副本吗?恕我直言,这应该重新打开 “重复”只是询问 如果 main() 是否超载(不是)。这个问题很清楚事实,并询问原因。完全不重复,投票支持重新开放。 【参考方案1】:

为什么在 C++ 中 main() 函数没有被重载来获取 std::vector argv 而不是旧的 char* argv[]

因为这需要依赖<string>。 C++ 的理念始终是“不要为不使用的东西付费”。如果有人不想要 string 提供的自动内存管理,那么他们就无法强制执行。第二个观点:如果某些平台没有任何库支持,那么您将无法启动你的 C++ 程序!!

相反,intchar** 参数是内置的和独立的类型。人们总是可以在 main() 上编写自定义包装器,这完全可以满足需要。

编辑:关于 AProgrammer 的评论: 假设main(vector<string>)是允许的;那么如果一个平台符合所有 C++ 特性,但没有标准库支持,那么它将变得不符合标准。

【讨论】:

如何在不阻止int main(int, char**) 的情况下允许int main(std::vector<std::string>) 的可能性会打破只有在使用时才付费 的理念? @AProgrammer:实际上标准允许实现为main添加新的有效选项,只要它仍然允许标准中定义的两个选项。跨度> “第二个观点”是假的。甚至没有向量和字符串的 C++“实现”与 C 的一致性相差甚远,甚至无法运行 很多 简单、符合标准、惯用的 C++ 代码。此外,按照这种逻辑,我们根本不应该使用 C++……或 C. @delnan:比这要复杂一些。有些编译器出厂时没有标准库实现,您需要提供一个。在某些情况下,编译器附带标准库的实现,但您不想使用它(在我的工作室中,我们使用我们自己的调整标准库,Electronic Arts 和其他一些......)。并不是说它不能完成,但编译器必须读取 your 包含并使用任何头文件 you 必须生成一个蹦床函数,你可以在一个衬垫中自己编写. 好吧,我想说缺少标准库的实现首先不符合标准(因此没有 C++ 实现)。但是我完全可以理解您关于不将依赖项引入非内置类型的论点,即使这些是标准提供的。无论如何+1,因为它是第一个从更基本的“为什么标准是这种方式”的角度来解决这个问题的人——从其他回答者的角度而不是“为什么它不起作用”的角度。【参考方案2】:

基本上,std::vector 与 char * 数组不同(在内存布局或其他方面)。为此,您必须让编译器识别新的 main 声明,并在创建字符串向量的条目上添加一个包装器。

既然你这样做了,你也可以把 argc 扔掉,并声明 main be

int main(std::vector<std::string> argv)

但它适用于编译器。你必须让很多人认为这是值得的。

否则你可以自己做

int main(int argc, char **argv)

    std::vector<std::string> args;
    args.reserve(argc);
    for (std::size_t arg = 0; arg < argc; ++arg)
    
         args.push_back(argv[i]);
    
    return mymain(args);

不保证代码可以编译或工作,因为我只是在脑海中写下它。

或者(更好,感谢 AProgrammer)

int main(int argc, char **argv)

    return mymain(std::vector<std::string>(argv, argv + argc));

【讨论】:

std::vector&lt;std::string&gt; args(argv, argv+argc); 就足够了。我不认为它的性能敏感到足以保证储备。 @AProgrammer:不仅它不够敏感(通常没有那么多参数),而且在许多实现中,采用 2 个迭代器的构造函数(本例)执行单个分配。跨度> @TomTanner 这个电话可能是针对新的 C++ 程序员的。我是物理学家而不是程序员,但在我们的 C++ 课程中,教授告诉我们使用 std::vector 或 std::array 代替 C 数组。我们没有在 C 类数组中看到,也没有在字符串中看到 char*... @R.M.哇,你是少数从一开始就接受正确 C++ 培训的幸运儿之一。 C++ 不进行垃圾收集。由程序员来释放他们分配的内存。智能指针对此有所帮助,仅此而已【参考方案3】:

为什么不在标准中?简单:

因为没有人提出它。

事情进入 C++ 标准是因为有人为它写了一个提案,然后让其他人对其进行投票并合并它。除非有人真的想要它发生,否则它不会发生。

考虑到这个功能实际上是多么微不足道:

int main(int argc, char **argv)

    std::vector<std::string> args(argv, argv + argc);
    ...

没有任何真正的需要。这是一个方便的功能,与替代方案相比,它甚至没有使事情变得方便。

【讨论】:

我总是在这里听 C++ 程序员的 SO,他们停止使用 char[]char* 并在 C++ 中使用 std::string。那为什么至今没人提出呢?【参考方案4】:

编译器编译定义为的 main 是微不足道的

int main(std::vector<std::string> args) 
    ...

因为它已经写成

int main(int __argc, char **__argv) 
    std::vector<std::string> args(__argv, __argv+__argc);
    ...

允许任何容器(甚至是自定义容器)几乎一样容易,而不仅仅是std::vector&lt;std::string&gt;。 但它不是标准的,因为 - 为什么标准中没有这个的标准答案 - 没有人提出它并说服足够多的人这是一个好主意。我不认为有一个提议,所以可能没有理由拒绝它。对于大多数相关人员来说,更改可能很简单。

【讨论】:

【参考方案5】:

我怀疑,主要原因是通常的实现是 使其成为extern "C" 函数,并带有可变参数。在很多 实现,它是调用 main 的 C 运行时库。

有很多方法可以解决这个问题,但似乎没有一个值得费心, 考虑到将参数转换为您想要的任何内容是多么容易。

【讨论】:

以上是关于为啥 C++ 中的 main() 没有重载以使用 std::string?的主要内容,如果未能解决你的问题,请参考以下文章

c++中重载输出操作符,为啥要返回引用

为啥 C++ 中的 main() 不能内联?

C++入门(命名空间缺省参数函数重载引用内联函数)

Dev C++为啥不支持以void main()为主函数的空函数C程序?老师给出的一直都是以Tu

c++中为啥赋值运算符重载返回类型是引用

为啥 Typescript 不以正确的方式支持函数重载?