2013-06-06 4 views
3

Скажем, у меня есть следующий класс шаблона с статической функции-члена, что само по себе создает экземпляр статической переменной (которая функционально статическая переменная-член экземпляра в первый раз, содержащий его рутина называется):В каком объектном файле содержится следующая статическая шаблонная «переменная-член»?

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

     return value; 
    } 
}; 

Если я использую foo<T> в нескольких единицах перевода для некоторого T, в который файл объекта компилятор ставит foo<T>::mystatic::value? Как это очевидное дублирование/конфликт разрешено во время соединения?

+0

Возможно, вам лучше попросить об этом в другом месте, я не уверен, что на это может ответить любой, кроме автора компилятора. Я думаю, что 'value' имеет внешнюю связь, однако, потому что это не в области файлов. –

+0

@dauphic: Я не уверен, что вы подразумеваете под вашим замечанием «значение» с внешней связью ». В C++ объект, определенный в локальной области, не может иметь внешнюю связь. В приведенном выше примере 'value' имеет * отсутствие связи * с точки зрения C++. Однако, чтобы удовлетворить требованиям языка, типичная реализация будет сообщать 'значение' как внешний символ в объектном файле. – AnT

ответ

1

Вы понимаете, что ваша функция mystatic является функцией внешней связи? Это означает, что существует один и тот же конфликт между несколькими определениями mystatic, выполненными в разных единицах перевода. Кроме того, точно такая же проблема может возникнуть без шаблонов: обычные функции inline с внешней связью, определенные в файлах заголовков, могут создавать одинаковый кажущийся конфликт с множественным определением (и такая же проблема с локальной статической переменной также может быть воспроизведена там).

Для разрешения таких конфликтов все такие символы обозначаются компилятором определенным образом, зависящим от реализации. Делая это, компилятор связывается с компоновщиком с тем фактом, что эти символы могут легально заканчиваться в несколько раз. Например, одна известная реализация помещает такие символы в отдельный раздел объектного файла (иногда называемый «COMDAT»). Другие реализации могут обозначать такие символы каким-либо другим способом. Когда компоновщик обнаруживает такие символы в нескольких объектных файлах, вместо сообщения об ошибке множественного определения, он выбирает один и только один каждого идентичного символа и использует его на протяжении всей программы. Другие копии каждого такого символа отбрасываются компоновщиком.

Одним из типичных последствий этого подхода является то, что ваша локальная статическая переменная value должна быть включена как внешний символ в каждый объектный файл, несмотря на то, что у него нет связи с языковой точки зрения. Имя символа обычно будет состоять из имени функции mystatic и имени переменной value и некоторых других механизмов.

Других слов, собственно компилятор помещает оба определение mystatic и переменная value в все независимых объектных файлов, которые используют функцию члена. Затем компоновщик будет убедиться, что в связанной программе будет существовать только один mystatic и только один value. Вероятно, нет возможности определить, какой исходный объектный файл предоставил оставшуюся копию (если такое различие даже имеет смысл).

+0

Отличный ответ, спасибо. Я понимаю, что это сложная деталь реализации компилятора/компоновщика, но случай использования заставил меня задаться вопросом, как был разрешен видимый конфликт. – fbrereto

 Смежные вопросы

  • Нет связанных вопросов^_^