Этот ответ пытается прояснить, почему адрес локальной переменной не может быть constexpr
, анализируя пример для архитектуры x86-64.
Рассмотрим следующую игрушечную функцию print_addr()
, которая отображаетадрес его локальной переменной local_var
и рекурсивный вызов n
раз:
void print_addr(int n) {
int local_var{};
std::cout << n << " " << &local_var << '\n';
if (!n)
return; // base case
print_addr(n-1); // recursive case
}
При вызове print_addr(2)
в моей системе x86-64 был получен следующий вывод:
2 0x7ffd89e2cd8c
1 0x7ffd89e2cd5c
0 0x7ffd89e2cd2c
Как видите, соответствующие адреса local_var
различны для каждого вызова на print_addr()
.Также видно, что чем глубже вызов функции, тем ниже адрес локальной переменной local_var
.Это связано с тем, что на платформе x86-64 стек увеличивается вниз (т. Е. С более высоких адресов на более низкие).
Для вышеприведенного вывода стек вызовов будет выглядеть следующим образом наПлатформа x86-64:
| . . . |
Highest address ----------------- <-- call to print_addr(2)
| print_addr(2) |
-----------------
| print_addr(1) |
-----------------
| print_addr(0) | <-- base case, end of recursion
Lowest address ----------------- Top of the stack
Каждый вышеприведенный прямоугольник представляет кадр стека для каждого вызова print_addr()
.local_var
каждого вызова находится в соответствующем кадре стека.Поскольку local_var
каждого вызова print_addr()
находится в своем (другом) стековом кадре, адреса local_var
отличаются.
В заключение, поскольку адрес локальной переменной в функции может не совпадать для каждого вызова функции (т. Е. Кадр стека каждого вызова может находиться в другой позиции в памяти), адрестакой переменной не может быть определено во время компиляции, и поэтому не может быть квалифицировано как constexpr
.