Константные выражения и constexpr в C++

глубокое обучение

Постоянное выражение:

\

Значение не изменяется, и выражение оценивается как результат во время компиляции.

Естественно включает литералы, константные объекты, инициализированные константными выражениями. как:

\

const int a=24;//a - константное выражение

const int b=a+1;//b также является константным выражением

int c=8;//c не является, обычный int вместо const int

const int len=get_size();//len нет, потому что конкретное значение известно только во время выполнения

\

Две переменные constexpr

\

Как указано в стандарте C++11, разрешается объявлять переменную как тип constexpr, чтобы компилятор мог проверить, является ли значение переменной константным выражением.

Переменная, объявленная как constexpr, должна быть константой и должна быть инициализирована константным выражением!

\

constexpr int a=24;//24 инициализируется как константное выражение

constexpr int b=a+1;//a+1 также является константным выражением

constexpr int len=get_size();//истина только в том случае, если get_size() является функцией constexpr!

\

Особое отличие:

const int *p=nullptr;//p — указатель на целочисленную константу!

constexpr int *q=nullptr;//q — постоянный указатель на целое число!

\

Примечание. Переменные, определенные в теле функции, обычно не хранятся по фиксированным адресам (локальные переменные), и указатель constexpr не может указывать на

такие переменные. Конечно, переменные вне функции (статические) имеют фиксированные адреса и могут использоваться для инициализации указателей constexpr. Кроме того, в теле функции

Переменные (статические), которые определены, но область действия которых находится за пределами тела, также могут использоваться для указания с помощью constexpr. Если вне функции находится:

\

int a=0;

constexpr int b=24;

Затем в теле функции выполните:

constexpr const int *p=&a;//p — постоянный указатель, указывающий на целочисленную константу a

constexpr int *p1=&b;//p1 — постоянный указатель, указывающий на целое число b

\

Три функции constexpr

\

Этот тип функции можно использовать в константных выражениях, возвращаемое значение и все формальные параметры имеют литеральный тип, а в теле функции должен быть только один оператор возврата.

Примечание: Тип литерального значения здесь не означает одно буквальное значение.Тип литерального значения включает в себя арифметические типы, ссылки, указатели, перечисления и некоторые ограниченные классы.

\

constexpr int func(){return 24;}

constexpr int num=func();//Верно! !

\

Разрешить возвращаемое значение функции constexpr не постоянное. как

constexpr int getNum(int i){return i*2;}

\

Если arg в getNum(arg) не является постоянным выражением, то getNum(arg) не является постоянным выражением, например: \

int a=20;

getNum(a);

\

Если arg в getNum(arg) является константным выражением, то getNum(arg) также является константным выражением, например:

constexpr int a=20;

getNum(a);

\

Связь четырех встроенных функций и функций constexpr

\

Преобразование некоторых коротких и мощных функций в функцию имеет преимущества хорошей удобочитаемости, единообразного поведения, простоты модификации и повторного использования;

Недостаток в том, что вызов функции подразумевает ряд работ, сохранение регистров, ответ на сцену при возврате и даже копирование аргументов разного рода.

\

Если inline добавляется перед возвращаемым типом функции,

Указание в качестве встроенного означает, что он может быть расширен «встроенным» там, где он вызывается, без накладных расходов на выполнение функции.

\

При выполнении задачи инициализации компилятор заменяет вызов функции constexpr значением результата, чтобы иметь возможность расширения в любой момент во время компиляции,

Функция constexpr была неявно указана как встроенная функция!

\

Существуют определения встроенных функций, мы видим, что встроенные функции отличаются от других функций и могут быть определены несколько раз по следующим причинам:

Компилятор хочет расширить функцию только объявлением функции недостаточно, ему нужно знать поведение определения функции.

\

Конечно, для данной встроенной функции несколько определений должны быть абсолютно одинаковыми, поэтому ее определение можно поместить в заголовочный файл.

\

\

\

\

\

\

\

\

\

\

\