哪个对象文件包含以下静态模板化的“成员变量”?

时间:2013-06-06 00:04:13

标签: c++ templates static-methods static-members object-files

假设我有以下模板类,其中包含一个静态成员函数,该函数本身实例化一个静态变量(在第一次调用其包含例程时,它实际上是一个静态成员变量):

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

        return value;
    }
};

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

1 个答案:

答案 0 :(得分:1)

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

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

这种方法的一个典型结果是,您的本地静态变量value必须作为外部符号包含在每个目标文件中,尽管它从语言的角度来看没有链接。符号的名称通常由函数名mystatic和变量名value以及其他一些错误组成。

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