【问题标题】:Can the main (or entry-point) function be implemented as a lambda?主要(或入口点)函数可以实现为 lambda 吗?
【发布时间】:2011-12-12 16:18:06
【问题描述】:

这在最近更新的标准下是否有效?

auto main = [](int argc, char* argv[]) -> int
{
    return 0;
};

我的最佳猜测是它取决于 main() 是否必须是一个函数,或者是否允许它是任何可调用的全局范围符号(使用 ())。

【问题讨论】:

    标签: c++ lambda c++11 main


    【解决方案1】:

    不,main 必须是全局函数,不能是函数对象或其他任何东西。请参阅 ISO/IEC 14882:2011 § 3.6.1 主要功能。

    一个程序应包含一个名为 main 的全局函数,它是程序的指定开始。

    从第 2 段开始

    所有实现都应允许以下两种定义 主要:

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

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

    实现不需要允许任何其他定义。

    【讨论】:

    • 引用标准会使答案变得更好:) 特别是当您知道确切的部分时。
    • 有机会引用标准吗?
    • 正确。然而,在技术上生成的汇编代码并不能保证 main 甚至是一个函数,因此递归调用 main 具有未定义的行为:-)
    • 允许这两个定义并不能说明替代定义。
    • 是的,所以实现可以支持它,但本节似乎不需要它。
    【解决方案2】:

    不,原因如下:

    [n3290: 3.6.1/1]: 程序应包含一个名为的全局函数 main,这是程序的指定开始。它是 实现定义一个程序是否在一个独立的环境中 需要定义一个主函数。 [ 注意: 在一个独立的 环境、启动和终止是实现定义的; 启动包含执行对象的构造函数 具有静态存储持续时间的命名空间范围;终止包含 为具有静态存储持续时间的对象执行析构函数。 ——尾注 ]

    Lambda 不是函数,而是函数对象或函子:

    [n3290: 5.1.2/3]: lambda-expression 的类型(即 也是闭包对象的类型)是一个唯一的、未命名的非联合 类类型——称为闭包类型——其属性如下所述。 [..]

    【讨论】:

    • 有趣的是,当您尝试执行此操作时,Visual C++ 2010 将出现链接错误,但是,如果您重新定义捕获的 lambda 对象的入口点,它会编译并链接正常,然后崩溃尝试执行入口点时发生访问冲突。
    • @MichaelPrice:我不确定这里是否需要诊断。具体规则我记不得了。
    【解决方案3】:

    main() 必须是一个函数,因为它是从系统库内部调用的方式。它是 POSIX.1 标准的一部分,管理着 C 链接的工作方式

    主链接必须是外部全局的,不能内联或设为静态,因为它是从 libc 内部调用的,通常是从名为 _start 的函数调用的。

    例如,glibc中_start的典型实现是:

    int _start() {
         __libc_init(argc, argv, __environ);
         exit(main(argc, argv, __environ));
    }
    

    各种 libc 实现都会以类似的方式进行。

    在 C++ 中,主函数必须在全局范围内声明(即)::main();再次因为它是从一个类似init的函数调用的,例如执行后在上面的*nix函数上的_start for libc......

    【讨论】:

    • C 是一条红鲱鱼。 C++ 编译器无论如何都会忽略这一点,因为它们需要在调用 main 之前插入额外的代码来调用全局变量的 ctor。显然,他们也需要初始化 C++ 库,而不仅仅是 libc。
    猜你喜欢
    • 2019-10-05
    • 2018-05-10
    • 2015-11-19
    • 1970-01-01
    • 1970-01-01
    • 2012-09-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多