哪个对象文件包含以下静态模板化"member variable"?



假设我有下面的模板类,它有一个静态成员函数,它本身实例化了一个静态变量(从功能上讲,它是在第一次调用包含它的例程时实例化的静态成员变量):

template <typename T>
struct foo
{
    static int& mystatic()
    {
        static int value;
        return value;
    }
};

如果我在多个翻译单元中使用foo<T>为某些T,编译器将foo<T>::mystatic::value放入哪个目标文件?如何在链接时解决这种明显的重复/冲突?

您知道您的函数mystatic是一个具有外部链接的函数吗?这意味着在不同翻译单元中对mystatic的多个定义之间存在着同样的冲突。此外,没有模板也会出现完全相同的问题:在头文件中定义的具有外部链接的普通inline函数可以产生相同的明显的多定义冲突(对于局部静态变量也可以在那里重现相同的问题)。

为了解决这样的冲突,所有这样的符号都由编译器以某种与实现相关的方式进行标记。通过这样做,编译器向链接器传达这样一个事实,即这些符号可以合法地被多次定义。例如,一种已知的实现将这些符号放入目标文件的单独部分(有时称为"COMDAT"部分)。其他实现可能以其他方式标记这些符号。当链接器在多个目标文件中发现这样的符号时,它不会报告多重定义错误,而是选择且只选择每个相同符号中的一个,并在整个程序中使用它。每个这样的符号的其他副本将被链接器丢弃。

这种方法的一个典型后果是,你的局部静态变量value将不得不作为一个外部符号包含到每个目标文件中,尽管从语言的角度来看它没有链接。符号名通常由函数名mystatic和变量名value以及其他一些混淆组成。

换句话说,编译器正确地将mystatic的定义和变量value放入所有使用成员函数的独立的对象文件中。链接器稍后将确保在链接的程序中只存在一个mystatic和一个value。可能无法确定哪个原始目标文件提供了幸存的副本(如果这种区分有意义的话)。

最新更新