我有一个静态库,它是使用g ++从linux上的许多cpp文件生成的。一个头文件包含一个实现工厂模式的类
头文件中的伪代码如下
class Factory
{
public:
static Factory& instance();
Base * create(const std::string& name);
template<class T>
void register_class(const std::string& name);
}
template <class T>
class FactoryRegister
{
public:
FactoryRegister(const std::string& name)
{
Factory::instance().register_class<T>(name);
}
}
Factory的cpp文件具有实现。在另一个cpp文件Derive.cpp中,有一个我想注册到Factory的类。为此,我定义了一个全局变量。代码如下
FactoryRegister<Derive> g_register_derive("derive");
所有这些文件都被编译到一个静态库中,并链接到一个可执行文件。
我的理解是,由于g_register_derive未被任何代码引用,因此除非提供了完整归档选项,否则不应将其链接到可执行文件中。
奇怪的部分是,如果我将g_register_derive放在Derive.cpp中,则确实该符号未链接到可执行文件中。但是,如果我将g_register_derive放在Factory.cpp中,它将链接到可执行文件。
我用nm验证了结果,还有一行代码调用Factory::instance().create("Derive")
,它们也可以用来检查g_register_derive是否链接。
当然,如果我提供了完整归档选项,则g_register_derive将始终链接到可执行文件中。
答案 0 :(得分:1)
请参见here
了解与静态库的链接,尤其是默认情况下,只有链接器需要时,静态库中的目标文件libx.a(p.o)
才会被提取并链接到程序中。
如果链接器需要链接存档成员libx.a(p.o)
以便
解析对该对象文件中定义的符号foo
的一些先前引用,
那么在bar
中也定义的任何其他符号libx.a(p.o)
的定义
也链接到程序中-因为它是该目标文件的一部分-是否
程序是否引用了bar
。
因此,如果您在编译的源文件g_register_derive
中定义p.cpp
到p.o
并存档为libx.a(p.o)
,并且您的应用程序需要链接
libx.a(p.o)
出于任何原因,默认情况下, 1 g_register_derive
变为
在程序中定义。
如果将g_register_derive
的定义移至
q.cpp
(已编译并存档为libx.a(q.o)
)和您的应用程序
出于某种原因不需要需要链接libx.a(q.o)
,然后g_register_derive
在您的程序中未定义。
[1]使用非默认编译和链接选项,您可以删除定义 程序中的未使用符号。请参阅the Stackoverflow tag wiki about static-libraries和接受的答案。