Бесплатный курс по C++. Зарегистрируйтесь для отслеживания прогресса →

C++: Квалификаторы const и constexpr

В этом уроке мы познакомимся с константами и узнаем какие виды констант бывают в С++.

До сих пор все переменные, которые мы видели, были непостоянными, то есть их значения можно изменить в любое время. Однако иногда бывает полезно определять переменные со значениями, которые нельзя изменить. Например, есть математическая постоянная число Пи: 3,14. Маловероятно, что в ближайшее время оно изменится. Определение этого значения как константы помогает гарантировать, что оно не будет случайно изменено.

Чтобы сделать переменную константой, просто поместите ключевое слово const до или после типа переменной, например:

const double kPi { 3.14 };
int const kMonthInYear { 12 };

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

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

const double kGravity; // ошибка компиляции, должна быть инициализирована при определении

Обратите внимание, что константные переменные могут быть инициализированы из других переменных:

int main() {
  std::cout << "Enter your age: ";
  int age {};
  std::cin >> age;

  const int kUsersAge { age };
}

Константы времени выполнения и константы времени компиляции

На самом деле C++ имеет два разных типа констант.

Константы времени выполнения – это те, значения инициализации которых могут быть вычислены только во время выполнения, когда ваша программа работает. Такие переменная, как kUsersAge в приведенном выше фрагменте, является константой времени выполнения, поскольку компилятор не может определить ее начальное значение во время компиляции. kUsersAge полагается на ввод данных пользователем (который может быть предоставлен только во время выполнения). Однако после инициализации значение этой константы изменить нельзя.

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

const double kGravity { 9.8 };

Переменная kGravity выше является примером постоянной времени компиляции. Константы времени компиляции позволяют компилятору выполнять оптимизацию, недоступную для констант времени выполнения. Например, всякий раз, когда используется kGravity, компилятор может просто заменить идентификатор kGravity литералом 9.8 типа double.

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

int main() {
  constexpr double kGravity { 9.8 }; // значение 9,8 может быть определено во время компиляции
  constexpr int kSum { 4 + 5 };      // значение 4 + 5 может быть определено во время компиляции

  std::cout << "Enter your age: ";
  int age{};
  std::cin >> age;
  constexpr int kMyAge { age }; // ошибка компиляции
}

В этом уроке мы познакомились с константами в С++ и узнали что константы бывают двух видов: времени выполнения и времени компиляции.

Задание

Допишите программу, которая принимает в качестве аргумента командной строки радиус, находит длину окружности и выводит ее на экран. Длина окружности вычисляется по формуле: С = 2 * pi * r. Число Пи задайте константой.

Упражнение не проходит проверку — что делать? 😶

Если вы зашли в тупик, то самое время задать вопрос в «Обсуждениях». Как правильно задать вопрос:

  • Обязательно приложите вывод тестов, без него практически невозможно понять что не так, даже если вы покажете свой код. Программисты плохо исполняют код в голове, но по полученной ошибке почти всегда понятно, куда смотреть.
В моей среде код работает, а здесь нет 🤨

Тесты устроены таким образом, что они проверяют решение разными способами и на разных данных. Часто решение работает с одними входными данными, но не работает с другими. Чтобы разобраться с этим моментом, изучите вкладку «Тесты» и внимательно посмотрите на вывод ошибок, в котором есть подсказки.

Мой код отличается от решения учителя 🤔

Это нормально 🙆, в программировании одну задачу можно выполнить множеством способов. Если ваш код прошел проверку, то он соответствует условиям задачи.

В редких случаях бывает, что решение подогнано под тесты, но это видно сразу.

Прочитал урок — ничего не понятно 🙄

Создавать обучающие материалы, понятные для всех без исключения, довольно сложно. Мы очень стараемся, но всегда есть что улучшать. Если вы встретили материал, который вам непонятен, опишите проблему в «Обсуждениях». Идеально, если вы сформулируете непонятные моменты в виде вопросов. Обычно нам нужно несколько дней для внесения правок.

Кстати, вы тоже можете участвовать в улучшении курсов: внизу есть ссылка на исходный код уроков, который можно править прямо из браузера.

Полезное


Нашли ошибку? Есть что добавить? Пулреквесты приветствуются https://github.com/hexlet-basics
Если вы столкнулись с трудностями и не знаете, что делать, задайте вопрос в нашем большом и дружном сообществе