Псевдоним целых чисел со знаком и без знака во время оптимизации
Аsigned&
не может быть инициализирован из (и наоборот), но строгие правила алиасинга позволяют читать/записыватьsigned
объект черезunsigned&
(и наоборот), см. стандарт C++20 [basic.lval]#11.2 . Теоретически это можно использовать при оптимизации компилятора, если правило «как если бы» не нарушается.
Пример 1. Если я прав,f
может быть реализовано простым переходом к:
void foo(const unsigned& u);
void f(const signed& par)
{
foo(par);
}
Но все компиляторы загружаютpar
в регистр, сохранить регистр в стеке и передать местоположение стека вfoo
. Живая демонстрация.
Пример 2. Аналогично думаюg1
иg2
может указывать на одно и то же место в памяти:
const signed& g1 = 1;
const unsigned& g2 = g1;
Но компиляторы склонны выделять два разных места. Живая демонстрация.
Вопрос. Почему это? Разве это не упущенная возможность для оптимизации?
1 ответ
const signed& g1 = 1; const unsigned& g2 = g1;
Но компиляторы склонны выделять два разных места.
Здесь происходит то, что преобразуется во временныйunsigned int
и привязывается к этому временному. А C++ гарантирует, что разные объекты имеют разные адреса, поэтомуg1
иg2
нужно хранить отдельно.
То же самое с вашим примером функции. Ключевым моментом является то, что наличие разных адресов является наблюдаемым поведением. Эти функции могут полагаться на тот факт, что их аргументы имеют разные адреса, поскольку они являются ссылками на разные объекты. Если бы ваш компилятор объединил разные объекты в одно и то же пространство памяти, это наблюдаемое поведение изменилось бы, поэтому оно не подпадает под правило «как если бы».