3

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

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

        return value;
    }
};

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

4

1 回答 1

1

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

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

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

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

于 2013-06-06T01:10:14.973 回答