Оценка переменной 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 ?

3

Решение

Это зависит от рассматриваемого компилятора по многим параметрам. Какие виды оптимизации могут иметь место и т. Д. Однако 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, который на самом деле все еще выполняет вызов по обоим подсчетам для предположительно «теста» времени компиляции. Линии, которые я использовал, были

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 test int test (int) ’|

4

Другие решения


По вопросам рекламы ammmcru@yandex.ru
Adblock
detector