在另一个共享库中声明的静态对象的初始化规则是什么?例如,请考虑以下内容:
文件 X.hpp:
struct X {
X ();
static X const s_x;
};
struct Y {
Y (X const &) {}
};
文件 X.cpp:
#include "X.hpp"
#include <iostream>
X::X ()
{
std::cout << "side effect";
}
X const X::s_x;
我在静态库 libX.a
中编译了 X.cpp,并尝试链接以下可执行文件(文件 main.cpp):
#include "X.hpp"
int main ()
{
(void)X::s_x; // (1)
X x = s_x; // (2)
Y y = s_x; // (3)
}
只有 (1) 或 (2),什么也不会发生。但是如果我添加(3),静态对象被初始化(即打印“副作用”)。 (我使用 gcc 4.6.1)。
有没有办法预测这里会发生什么?
我不明白指令 (2) 为何不强制 X::s_x
对象默认构造,而 (3) 却强制构造。
编辑:构建命令:
g++ -c X.cpp
g++ -c main.cpp
ar rcs libX.a X.o
g++ -o test main.o -L. -lX
最佳答案
默认情况下,在许多平台上,如果您的程序没有引用静态库中给定目标文件中的任何符号,则整个目标文件(包括静态初始值设定项)将被删除。因此链接器忽略了 libX.a 中的 X.o,因为它看起来未被使用。
这里有几个解决方案:
- 不要依赖静态初始化器的副作用。这是最便携/最简单的解决方案。
- 通过以编译器无法识别的方式引用虚拟符号(例如将地址存储到外部可见的全局变量中),在每个文件中引入一些虚假的依赖关系。
- 使用一些特定于平台的技巧来保留相关对象。例如,在 Linux 上,您可以使用
-Wl,-whole-archive a.o b.a -Wl,-no-whole-archive
。
关于c++ - 链接静态库时静态对象的初始化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7327741/