实施例:C++静态初始化VS __attribute __((构造))
struct Foo { Foo() { printf("foo\n"); } };
static Foo foo;
__attribute__((constructor)) static void _bar() { printf("bar\n"); }
它是确定性的阉羊foo
或bar
是第一印刷?
(我希望和期望静态对象的构造函数总是执行有关构造属性不说什么第一,但不知道和GCC的文档)。
实施例:C++静态初始化VS __attribute __((构造))
struct Foo { Foo() { printf("foo\n"); } };
static Foo foo;
__attribute__((constructor)) static void _bar() { printf("bar\n"); }
它是确定性的阉羊foo
或bar
是第一印刷?
(我希望和期望静态对象的构造函数总是执行有关构造属性不说什么第一,但不知道和GCC的文档)。
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)));
这里,B
是A
之前进行初始化。
看起来不确定。在使用GCC编译时,我的问题中也有foo\nbar\n
作为示例的输出。但是,使用LLVM/Clang编译时,我得到了bar\nfoo\n
。
但是,因为我不知道这可能是铛的错误,我填一个bug报告here。 编辑:我在那里得到了答案,它似乎是一个真正的叮当中尚未修复的错误。不知道从那里得出什么结论。预期的和应该的行为在这里确实是确定性的,但是,你不能依赖它,因为至少有一个主要的编译器(Clang)做错了(或者不同于GCC,如果我们把它作为规范__attribute__((constructor))
)。
注意,这可能是在现实世界中的代码真正相关的和重要的。例如。 here是一个种子随机发生器失败与铿锵的例子。
你在哪里使用这种编译器功能? – AlexTheo
@AlexTheo:这很常见。见例如。每次你想要初始化某些东西时,你通常都会使用它。 –
Albert
其实我更喜欢像静态常量布尔_isInitialized 并且与我初始化我的物体,像常量布尔MyClass的一个私有的初始化函数:: _ =将IsInitialized initFunction(); 但是,这些仅适用于我喜欢首先初始化的对象。否则构造函数应该做一个工作。 – AlexTheo