2011-12-08 180 views
16

实施例:C++静态初始化VS __attribute __((构造))

struct Foo { Foo() { printf("foo\n"); } }; 
static Foo foo; 

__attribute__((constructor)) static void _bar() { printf("bar\n"); } 

它是确定性的阉羊foobar是第一印刷?

(我希望和期望静态对象的构造函数总是执行有关构造属性不说什么第一,但不知道和GCC的文档)。

+0

你在哪里使用这种编译器功能? – AlexTheo

+0

@AlexTheo:这很常见。见例如。每次你想要初始化某些东西时,你通常都会使用它。 – Albert

+0

其实我更喜欢像静态常量布尔_isInitialized 并且与我初始化我的物体,像常量布尔MyClass的一个私有的初始化函数:: _ =将IsInitialized initFunction(); 但是,这些仅适用于我喜欢首先初始化的对象。否则构造函数应该做一个工作。 – AlexTheo

回答

13

foo将首先打印,作为对象按其声明的顺序进行初始化。运行看:

顺便说一句,__attribute__((constructor))不是标准C++。这是GCC的延伸。所以你的程序的行为取决于GCC如何定义它。简而言之,它是实现定义的,根据它foo首先被打印。

doc的说,

构造属性导致函数被自动调用之前执行进入主()。同样,析构函数的属性也会导致函数在main()完成或exit()被调用后自动调用。具有这些属性的函数对于初始化将在程序执行过程中隐式使用的数据非常有用。

您可以提供一个可选的整数优先级来控制构造函数和析构函数的运行顺序。具有较小优先级编号的构造函数在具有较大优先级编号的构造函数之前运行;相反的关系适用于析构函数。所以,如果你有一个分配资源的析构函数和一个释放相同资源的析构函数,那么这两个函数通常具有相同的优先级。 构造函数和析构函数的优先级与为命名空间范围C++对象(请参阅C++属性)指定的优先级相同。

我想以粗体文字所暗示的,对象在其声明的顺序进行初始化,正如我以前说过,这是相当多的online demo证实也。

我猜你也想阅读:

如果你想控制/改变初始化顺序,您可以使用init_priority属性,提供优先。从the page摘自:

Some_Class A __attribute__ ((init_priority (2000))); 
Some_Class B __attribute__ ((init_priority (543))); 

这里,BA之前进行初始化。

+0

恩,所有评论被删除了?这怎么可能。所以,这里是我的评论:对我来说有趣的是这个信息和最后一个链接,特别是。这样的:*在标准C++,在名字空间域中定义的对象,保证在严格按照它们在一个给定的翻译单元定义的顺序进行初始化* – Albert

+0

事实上,我只是测试它在另一示例中,并且它不”。似乎是那里的情况。 – Albert

+0

@Albert:发布代码。实际的代码,没有改变它一点。还张贴你得到的输出。 – Nawaz

1

看起来不确定。在使用GCC编译时,我的问题中也有foo\nbar\n作为示例的输出。但是,使用LLVM/Clang编译时,我得到了bar\nfoo\n

但是,因为我不知道这可能是铛的错误,我填一个bug报告here编辑:我在那里得到了答案,它似乎是一个真正的叮当中尚未修复的错误。不知道从那里得出什么结论。预期的和应该的行为在这里确实是确定性的,但是,你不能依赖它,因为至少有一个主要的编译器(Clang)做错了(或者不同于GCC,如果我们把它作为规范__attribute__((constructor)))。

注意,这可能是在现实世界中的代码真正相关的和重要的。例如。 here是一个种子随机发生器失败与铿锵的例子。

+0

删除这篇文章。并编辑你的问题,并发布到那里。答案应该是答案,而不是问题。 – Nawaz

+1

@Nawaz:你是什么意思?为什么?这是一个答案,我的问题是一个问题。如果你不清楚这个答案的答案是否是真正的问题:它基本上说它是不确定的。 – Albert

+0

好的。你怎么能说它是非确定性的,你怎么能这样说:“*因此,看起来rnd的构造函数是在_rand_engine__init *之后执行的。也发布一些解释! – Nawaz