C ++ Makefile编译顺序

时间:2013-07-20 20:25:48

标签: c++ makefile g++ global-variables clang++

嗨,在这个问题中,我读到编译顺序并不重要,但我的情况非常奇怪。

我在文件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()和CCLayoutParamsWrapWrap.getHeight()

这应该输出-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)发生了什么事?

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

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

2 个答案:

答案 0 :(得分:2)

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

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

我不知道gcc究竟是什么造成了差异,但我怀疑它是链接顺序而不是真正重要的编译顺序。但这只是一个猜测,如果你想确认或反驳它,你可以测试。重要的是你不应该依赖它,因为它不需要像那样。

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

答案 1 :(得分:2)

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

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