在执行时加载常量,一次还是两次? 我对加载C++生成的可执行文件有点困惑。我正在将一个巨大的常量字符串表放入目标可执行文件中。数据应嵌入可执行文件(无外部文件)

在执行时加载常量,一次还是两次? 我对加载C++生成的可执行文件有点困惑。我正在将一个巨大的常量字符串表放入目标可执行文件中。数据应嵌入可执行文件(无外部文件),c++,C++,在我们运行代码时编译并生成代码后,可能会出现两种情况: 操作系统加载巨大的可执行文件(需要时间),然后运行程序,然后程序就可以使用数组数据了 操作系统加载巨大的可执行文件(需要时间),然后运行程序,然后,程序必须生成表并加载字符串文本,并构造那些std::string对象(需要时间) 很明显,第二个比第一个慢 如何知道哪一个会发生 拥有大量嵌入式数据的最佳方法是什么(权衡:速度和空间) 使用工具objcopy有用吗(我没有这方面的经验) 我使用的是GCC4.7+,目标操作系统是Windows

在我们运行代码时编译并生成代码后,可能会出现两种情况:

  • 操作系统加载巨大的可执行文件(需要时间),然后运行程序,然后程序就可以使用数组
    数据了

  • 操作系统加载巨大的可执行文件(需要时间),然后运行程序,然后,程序必须生成表并加载字符串文本,并构造那些
    std::string
    对象(需要时间)

  • 很明显,第二个比第一个慢

    • 如何知道哪一个会发生
    • 拥有大量嵌入式数据的最佳方法是什么(权衡:速度和空间)
    • 使用工具objcopy有用吗(我没有这方面的经验)

    我使用的是GCC4.7+,目标操作系统是Windows/Linux/Android(NDK)

    在这种情况下,必须调用构造函数。示例中字符串的构造函数不能“在编译时完成”。[编辑:由于
    std::string
    必须调用
    操作符new()
    来分配内存(或以其他方式分配内存,尽管有时可以避免短字符串使用这种方法,但不太可能充分得出此决定,从而使编译器能够“就地”构建正确的数据结构。”--结束编辑]

    在这种特殊情况下,您可以通过使用
    const char*
    而不是
    std::string
    来避免构造,但前提是字符串不会被修改,这当然可能是一个拉伸[如果在使用前需要将所有字符串都设置为
    std::string
    ,并且使用大表中的所有字符串,则几乎没有任何好处]

    顺便说一句,(在大多数操作系统中)程序不会加载“一次完成所有代码,需要很长时间”的代码。相反,它加载“入口点”(在一个4KB的块中,这是保持入口点的4KB对齐的代码块)。其他一切都是“按需加载的”——也就是说,它是根据需要加载的。

    普通旧数据(POD)可以在编译和链接时准备,并存储在可执行文件中,因此只需将其加载到内存中即可使用。但是,具有构造函数的类的任何成员数据都可能需要调用构造函数

    我使用Apple clang 4.0 for x86_64编译了代码,检查了生成的代码,并逐步执行了部分代码。它确实调用了字符串构造函数,并且调用了
    malloc


    理论上,一个积极的C++实现可以将大部分的工作迁移到编译和链接时间,但是你应该普遍期望这样的数据会导致在程序启动时调用构造函数和内存分配。

    struct DataRecord
    {
        unsigned char n1;
        unsigned char n2;
        std::string text;
    };
    
    static const DataRecord data[] = {
        {1, 2, "Hello"},
        {1, 3, "Hi"},
        {1, 4, "Bye"}
        .
        .
        VERY LONG LIST    
        .
        .
    };