Я хотел бы отслеживать то, что по сути является «типовой» информацией во время компиляции для нескольких функций, которые в настоящее время принимают аргументы того же типа. Вот пример; Скажи у меня две функции getThingIndex(uint64_t t)
а также getThingAtIndex(uint64_t tidx)
, Первая функция обрабатывает аргумент как кодировку thing
, выполняет нетривиальное вычисление индекса и возвращает его. Затем можно получить фактическую «вещь», позвонив getThingAtIndex
, getThingAtIndex
с другой стороны, предполагается, что вы запрашиваете структуру и уже имеете индекс. Последний из двух методов работает быстрее, но, что более важно, я хочу избежать головной боли, которая может возникнуть в результате передачи thing
в getThingAtIndex
или передавая index
в getThingIndex
,
Я думал о создании типов для thing
и индекс вещей вроде как так:
struct Thing { uint64_t thing; }
struct ThingIndex { uint64_t idx; }
А затем изменить подписи функций выше, чтобы
getThingIndex(Thing t)
getThingAtIndex(ThingIndex idx)
Теперь, несмотря на то, что Thing
а также ThingIndex
закодировать то же самое
базовый тип, они тем не менее различаются во время компиляции, и я
меньше возможностей совершать глупые ошибки, передавая индекс
getThingIndex
или вещь для getThingAtIndex
,
Тем не менее, я обеспокоен накладными расходами этого подхода. Функции
называются много (от 10 до 100 миллионов) раз, и мне любопытно, если
компилятор оптимизирует создание этих структур, которые по существу
ничего не делать, кроме как кодировать информацию типа времени компиляции. Если компилятор не
выполнить такую оптимизацию, есть ли способ создать эти типы «богатых типов» с нулевыми издержками?
Посмотрите на разборку.
unsigned long long * x = new unsigned long long;
0110784E push 8
01107850 call operator new (01102E51h)
01107855 add esp,4
01107858 mov dword ptr [ebp-0D4h],eax
0110785E mov eax,dword ptr [ebp-0D4h]
01107864 mov dword ptr [x],eax
*x = 5;
01107867 mov eax,dword ptr [x]
0110786A mov dword ptr [eax],5
01107870 mov dword ptr [eax+4],0
И структура.
struct Thing { unsigned long long a; };
Thing * thing = new Thing;
0133784E push 8
01337850 call operator new (01332E51h)
01337855 add esp,4
01337858 mov dword ptr [ebp-0D4h],eax
0133785E mov eax,dword ptr [ebp-0D4h]
01337864 mov dword ptr [thing],eax
thing->a = 5;
01337867 mov eax,dword ptr [thing]
0133786A mov dword ptr [eax],5
01337870 mov dword ptr [eax+4],0
Там нет никакой разницы в двух инструкциях. Компилятору все равно this->a
является членом структуры, он обращается к ней, как будто вы только что объявили unsigned long long a
,
Других решений пока нет …