tgoop.com/cxx95/15
Create:
Last Update:
Last Update:
#madskillz
Указатели-коммуналки
Пусть мы хотим из метода вернуть какой-то объект вместе с булевыми флагами. Флаги это свойства, которые объект имеет. Тогда мы должны возвращать что-то вроде этого:
template<typename Ty> class ActionResult {
bool Invalid = false;
Ty T;
// некие методы...
};
Но некоторым проектам (например Clang) это ощутимые затраты по памяти из-за выравнивания и прочего. Если у вас много где есть работа с указателями, и
Ty
часто имеет тип указателя, то ActionResult
можно приспособить чисто для указателей.В этом случае флаги можно отселить... прямо вовнутрь ссылки:
template<typename PtrTy> class ActionResult {
uintptr_t PtrWithInvalid; // можно считать что sizeof(uintptr_t) == sizeof(PtrTy*)
};
Как это должно работать? Ссылочный тип в 64-бит архитектуре имеет размер 8 байт, и мог бы напрямую адресовать оперативку до объемом до 16 млн ТБ.
Отсюда получается, что некоторые биты из этих 8 байт (старшие) вообще не используются, потому что они заведомо равны нулю.
Можно отселить флаг
Invalid
в нулевой бит:bool isInvalid() const { return PtrWithInvalid & 0x01; }
bool isUsable() const { return PtrWithInvalid > 0x01; }
bool isUnset() const { return PtrWithInvalid == 0; }
А сам указатель сдвинуть на один бит, освобождая место флагу:
PtrTy get() const {
return reinterpret_cast<PtrTy *>((PtrWithInvalid & ~0x01) >> 1);
}
В Clang разрешено встраивать в указатель до трёх флагов (трёх битов): class PointerIntPair
Один из самых прикольных способов использования - класс
QualType
. Он содержит ссылку на чистый тип (Type*
) и флаги-наличие квалификаторов (const
, restrict
, volatile
).Из-за вышеописанной техники этот класс совершенно бесплатен по памяти!
BY C++95
Share with your friend now:
tgoop.com/cxx95/15