Ответ 1
Пока вы восстанавливаете младший бит указателя до того, как пытаетесь использовать его в качестве указателя, он, вероятно, будет "разумно" переносимым, если ваша система, ваша реализация C++ и ваш код соответствуют определенным предположениям.
Я не могу обязательно дать вам полный список предположений, но в верхней части моей головы:
- Предполагается, что вы не указываете ни на что, чей размер составляет 1 байт. Это исключает
char
,unsigned char
,signed char
,int8_t
иuint8_t
. (И это предполагаетCHAR_BIT == 8
; в экзотических системах, скажем, с 16-битными или 32-битными байтами, другие типы могут быть исключены.) - Предполагается, что объекты размером не менее 2 байтов всегда выровнены по четному адресу. Обратите внимание, что x86 не требует этого; Вы можете получить доступ к 4-байтовому
int
по нечетному адресу, но это будет немного медленнее. Но компиляторы обычно организуют хранение объектов по четным адресам. Другие архитектуры могут иметь другие требования. - Предполагается, что указатель на четный адрес имеет младший бит, установленный в 0.
Для этого последнего предположения у меня есть конкретный контрпример. В векторных системах Cray (J90, T90 и SV1 - те, которые я использовал сам), машинный адрес указывает на 64-битное слово, но компилятор C под Unicos устанавливает CHAR_BIT == 8
. Байтовые указатели реализованы в программном обеспечении, с 3-битным байтовым смещением в слове, которое хранится в неиспользуемых старших 3 битах 64-битного указателя. Таким образом, указатель на 8-байтовый выровненный объект может легко иметь младший бит равным 1.
Были реализации Lisp (пример), которые используют младшие 2 бита указателей для хранения тега типа. Я смутно помню, что это вызывало серьезные проблемы при портировании.
Итог: вы, вероятно, можете избежать неприятностей с большинством систем. Будущие архитектуры в значительной степени непредсказуемы, и я легко могу представить, как ваша схема сломается в следующем Большом Новом.
Некоторые вещи для рассмотрения:
Можете ли вы хранить логические значения в битовом векторе вне вашего класса? (Поддержание связи между указателем и соответствующим битом в битовом векторе оставлено в качестве упражнения).
Попробуйте добавить код ко всем операциям с указателями, которые завершаются неудачно с сообщением об ошибке, если он когда-либо видит указатель с битом младшего разряда, установленным в 1. Используйте #ifdef
, чтобы удалить проверочный код в рабочей версии. Если вы столкнетесь с проблемами на какой-либо платформе, создайте версию своего кода с включенными проверками и посмотрите, что произойдет.
Я подозреваю, что по мере роста вашего приложения (оно редко сжимается) вы захотите хранить больше, чем просто bool
вместе с указателем. Если это произойдет, проблема с пространством исчезнет, потому что вы все равно уже используете это дополнительное пространство.