C++Makefile编译顺序

C++ Makefile compilation order

本文关键字:顺序 编译 C++Makefile      更新时间:2023-10-16

嗨,在这个问题中,我读到编译顺序无关紧要,但我的情况真的很奇怪。

我在CCSizePolicy.cpp文件中有几个全局变量它们看起来像这样:

const CCSizePolicy CCSizePolicyWrapContent ( Const::WRAP_CONTENT );
const CCSizePolicy CCSizePolicyMatchContent ( Const::MATCH_PARENT );
const CCSizePolicy CCSizePolicyZero ( Policy::SP, 0 );

头标

    enum Const
    {
        WRAP_CONTENT = -1, MATCH_PARENT = -2
    };
extern const CCSizePolicy CCSizePolicyWrapContent;
extern const CCSizePolicy CCSizePolicyMatchContent;
extern const CCSizePolicy CCSizePolicyZero;

同样在CCLayoutParams.h 中

extern const CCLayoutParams CCLayoutParamsMatchMatch;
extern const CCLayoutParams CCLayoutParamsWrapWrap;
extern const CCLayoutParams CCLayoutParamsMatchWrap;
extern const CCLayoutParams CCLayoutParamsWrapMatch;

和CCLayoutParams.cpp

const CCLayoutParams CCLayoutParamsMatchMatch ( CCSizePolicyMatchContent,
        CCSizePolicyMatchContent );
const CCLayoutParams CCLayoutParamsWrapWrap ( CCSizePolicyWrapContent,
        CCSizePolicyWrapContent );
const CCLayoutParams CCLayoutParamsMatchWrap ( CCSizePolicyMatchContent,
        CCSizePolicyWrapContent );
const CCLayoutParams CCLayoutParamsWrapMatch ( CCSizePolicyWrapContent,
        CCSizePolicyMatchContent );

因此,当我在程序中使用它们时,我会调用CCLayoutParamsWrapWrap.getWidth()和CCLayoutParams WrapWrappe.getHeight()

这应该输出me-1-1但是我有0 0…

makefile中的订单如下:

src/view/layout/CCLayoutParams.cpp
...
src/view/CCSizePolicy.cpp

当我把它改成时

src/view/CCSizePolicy.cpp
src/view/layout/CCLayoutParams.cpp
...

一切都开始工作了(我得到-1-1)发生了什么?

我使用带有gcc版本4.6.3的Linux(Ubuntu/Linaro 4.6.3-1ubuntu5)

我的整个项目都被窃听了,我不知道为什么,因为我按名称对源文件进行排序??!?!

很可能,这不是文件编译的顺序,而是它们链接的顺序(我想这是由你的源所在的顺序定义的)-g++"收集"链接阶段变量的全局初始化,然后按照找到它们的顺序处理它们。然而,这恰好是"观察到的行为"。C++中不同编译单元之间的初始化是未定义的。你不能以这样或那样的方式依赖它,绝对没有什么可以阻止g++改变全局初始化的顺序,使其以相反的顺序而不是当前的顺序进行(因为这会使链接过程更快,或者其他一些聪明的原因-或者只是"感觉像这样")-他们甚至不必告诉你他们已经这样做了

所以,基本上,如果你有全局对象,那么你必须把它们放在一个单一的源文件("globalobjects.cpp"或类似的文件)中,使它们按照定义的顺序初始化,或者不依赖于一个在另一个之前初始化。或者依赖于模糊的定义,即"当前,只要我按正确的顺序放置文件,链接器就会按正确的次序进行操作"。

不同源文件中全局变量的初始化顺序未指定。因此,它可以取决于任何事情,例如包括文件的编译顺序。

在这种情况下,如果CCLayoutParamsWrapWrapCCSizePolicyWrapContent之前初始化,则其构造函数将看不到CCSizePolicyWrapContent的构造函数设置的值-1。相反,它将看到由所谓的"静态初始化"设置的值0,该值发生在"动态初始化"(即构造函数调用)之前。

我不知道gcc的具体原因,但我怀疑真正重要的是链接顺序,而不是编译顺序。不过,这只是一个猜测,如果你想证实或反驳它,你可以测试一下。重要的一点是,你不应该依赖它,因为它不需要那样做。

在C++11中,我认为可以通过确保CCSizePolicyWrapContent是一个具有constexpr构造函数的constexpr对象来解决这个问题。否则,您应该阅读有关"静态初始化顺序惨败"的内容,以及可用于对初始化顺序施加约束的各种技术,然后选择适合您情况的技术。