2009-11-30 11 views
9

Andrei Alexandrescu пишет в Modern C++ Design:Когда typeid может возвращать разные экземпляры type_info для одного и того же типа?

Объекты, возвращаемые typeid имеют статической памяти, так что вам не придется беспокоиться о пожизненных вопросов.

Андрей продолжает:

стандарт не гарантирует, что каждый вызов, скажем, typeid(int) возвращает ссылку на тот же type_info объекта.

Несмотря на то, что стандарт не гарантирует этого, как это реализовано в обычных компиляторах, таких как GCC и Visual Studio?

Предполагая, что typeid не просачивается (и возвращает новый экземпляр каждый звонок), это одна «таблица» для каждого приложения, на единицу перевода, за dll/so или что-то совершенно другое?

Есть еще раз, когда &typeid(T) != &typeid(T)?

Меня интересуют только компиляторы для Windows, но любая информация для Linux и других платформ также приветствуется.

+3

Важной причиной такого уровня свободы действительно была проблема с DLL. – MSalters

ответ

10

Существуют случаи, когда & TypeId (T)! = & TypeId (T)?

Меня интересуют только компиляторы для Windows, но любая информация для Linux и других платформ также приветствуется.

Да. Таким образом, под Windows DLL не могут быть неразрешенные символы. Если у вас есть:

foo.h

struct foo { virtual ~foo() {} }; 

dll.cpp

#include "foo.h" 
... 
foo f; 
cout << &typeid(&f) << endl 

main.cpp

#include "foo.h" 
... 
foo f; 
cout << &typeid(&f) << endl 

даст вам различные указатели.Поскольку перед загрузкой dll typeid (foo) должен существовать как в dll, так и в первичных exe

Более того, под Linux, если основной исполняемый файл не был скомпилирован с -rdynamic (или -export-dynamic), тогда typeid будет разрешено для разных символов в исполняемом файле и в общем объекте (что обычно не происходит на платформах ELF) из-за некоторых оптимизаций, выполняемых при связывании исполняемых файлов - удаление ненужных символов.

1

Стандарты иногда оставляют определенное поведение неуказанным, чтобы обеспечить реализацию некоторой свободы. В этом случае, как управляются TypeID, остается до реализации компилятора, и вам просто дают набор правил (по существу: не беспокойтесь о том, как выделяется память для этого).

Есть ли какая-то особая причина, по которой вам нужно иметь возможность сравнивать TypeIds на основе их адреса памяти? TypeIds уже переопределяют == и! =, Чтобы предоставить вам возможность сравнивать их и предоставлять имя(), которое может использоваться для однозначного определения их.

Если у вас есть язык программирования C++ (Bjarne Stroustrup), в главе 15 содержится много сведений об обработке иерархии классов. Может быть, вы найдете там другое решение?

+3

У вас много хороших моментов, но это не отвечает на мой вопрос. Мне не нужно сравнивать адреса, я просто заинтересован в том, как он обрабатывается внутри компиляторов. Но мои основные интересы в этом вопросе - это те, что написаны в компиляторе: как и почему это реализовано таким образом. Добавление дополнительных тегов к вопросу. – dalle