Когда typeid может возвращать разные экземпляры type_info для одного и того же типа?
-
10-07-2019 - |
Вопрос
Андрей Александреску пишет в Современный дизайн на C++:
Объекты, возвращенные
typeid
Иметь статическое хранилище, поэтому вам не нужно беспокоиться о проблемах на всю жизнь.
Андрей продолжает:
Стандарт не гарантирует, что каждый призыв, скажем,
typeid(int)
возвращает ссылку на то же самоеtype_info
объект.
Несмотря на то, что стандарт не гарантирует этого, как это реализуется в обычных компиляторах, таких как GCC и Visual Studio?
Предполагая typeid
не протекает (и возвращает новый экземпляр при каждом вызове), это одна «таблица» для каждого приложения, для каждой единицы перевода, для каждой dll/so или что-то совершенно другое?
Бывают ли моменты, когда &typeid(T) != &typeid(T)
?
В основном меня интересуют компиляторы для Windows, но я также буду рад любой информации для Linux и других платформ.
Решение
Бывают ли случаи, когда &typeid(T) != &typeid(T)?
В основном меня интересуют компиляторы для Windows, но я также буду рад любой информации для Linux и других платформ.
Да.Таким образом, под Windows DLL не может иметь неразрешенные символы.Если у вас есть:
фу.ч
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) из-за некоторых оптимизаций, сделанных при связывании исполняемых файлов - удаление ненужных символов.
Другие советы
Стандарты иногда оставляют определенное поведение неуказанным, чтобы дать реализациям некоторую свободу. В этом случае то, как обрабатываются TypeID, оставлено на усмотрение реализации компилятора, и вам просто дают набор правил (по сути: не беспокойтесь о том, как выделяется память для этого).
Есть ли какая-то особая причина, по которой вам нужно сравнивать TypeIds на основе их адреса памяти? TypeIds уже переопределяют == и! =, Чтобы предоставить вам возможность сравнивать их и предоставлять имя (), которое может использоваться для их уникальной идентификации.
Если у вас есть язык программирования C ++ (Bjarne Stroustrup), глава 15 содержит много подробностей об обработке иерархий классов. Может быть, вы могли бы найти другое решение там?