Оценка переменной Constexpr
Вот мой код, и мне нужно уточнить, что происходит:
constexpr int funct(int x){
return x + 1;
}
int main(){
int x = funct(10);
return 0;
}
constexpr
Это позволяет рассчитать время компиляции, и на основе моего кода выше, так как funct
объявлен как constexpr
, разрешено выполнять вычисления времени компиляции, если аргументы являются константами или самим constexpr.
Часть, которую я путаю с ложью в этой части, int x
, Поскольку он не объявлен как constexpr
это будет означать, что int x
получит значение во время выполнения? Означает ли это, что объявив его constexpr int x
будет означать, что int x получит значение во время компиляции в отличие int x
?
1 ответ
Это зависит от рассматриваемого компилятора по многим параметрам. Какие виды оптимизации могут иметь место и т. Д. Однако constexpr по своей сути не позволяет выполнять вычисления во время компиляции.
Возьми этот код:
#include <cstdio>
constexpr int test(int in)
{
return in + 25;
}
int main(int argc, char* argv[])
{
printf("Test: %u\n", test(5));
printf("Two: %u\n", test(10));
}
Согласно GCC 4.8.4 на моем x86_64 Gentoo box, он на самом деле по-прежнему выполняет вызов по обоим подсчетам для предположительно "теста" времени компиляции. Линии, которые я использовал, были
g++ -std=c++11 -Wall -g -c main.cpp -o obj/Debug/main.o
g++ -o bin/Debug/TestProject obj/Debug/main.o
Таким образом, в приведенном выше коде получается следующий машинный код:
0x40061c mov edi,0x5
0x400621 call 0x400659 <test(int)>
0x400626 mov esi,eax
0x400628 mov edi,0x4006f4
0x40062d mov eax,0x0
0x400632 call 0x4004f0 <printf@plt>
0x400637 mov edi,0xa
0x40063c call 0x400659 <test(int)>
0x400641 mov esi,eax
0x400643 mov edi,0x4006fd
0x400648 mov eax,0x0
0x40064d call 0x4004f0 <printf@plt>
Где блок asm для "теста":
0x400659 push rbp
0x40065a mov rbp,rsp
0x40065d mov DWORD PTR [rbp-0x4],edi
0x400660 mov eax,DWORD PTR [rbp-0x4]
0x400663 add eax,0x19
0x400666 pop rbp
0x400667 ret
Таким образом, как вы можете видеть в этой ситуации, похоже, что это не имеет никакого влияния на то, как GCC создал этот код. Даже если вы сделаете это, вы все равно получите вычисления во время выполнения:
int value = test(30);
printf("Value: %u\n", value);
Где это произойдет (адрес теста немного изменился из-за добавления еще кода):
0x40061c mov edi,0x1e
0x400621 call 0x40067a <test(int)>
0x400626 mov DWORD PTR [rbp-0x4],eax
0x400629 mov eax,DWORD PTR [rbp-0x4]
0x40062c mov esi,eax
0x40062e mov edi,0x400714
0x400633 mov eax,0x0
0x400638 call 0x4004f0 <printf@plt>
Однако он дает ожидаемый результат, если вы объявите само значение как constexpr:
constexpr int value = test(30);
printf("Value: %u\n", value);
И связанный код:
0x400623 mov esi,0x37
0x400628 mov edi,0x400714
0x40062d mov eax,0x0
0x400632 call 0x4004f0 <printf@plt>
По сути, вам не гарантируется вычисление времени компиляции, если вы просто добавляете объявление метода с помощью constexpr. Вам также нужно объявить вашу переменную как constexpr и присвоить ей. Выполнение такого объявления потребует от компилятора статической оценки результата. GCC на самом деле кричит на вас, если вы пытаетесь это сделать, а "test" не объявлен constexpr:
main.cpp | 10 | ошибка: вызов функции non-constexpr 'int test(int)' |