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
