Содержание
Тернарный оператор ?: выбирает одно из двух значений по условию. Это короткая запись if ... else для случая, когда обе ветки дают значение: что присвоить, что вывести, что вернуть из функции.
Синтаксис
условие ? значение_если_истина : значение_если_ложь
Сначала вычисляется условие. Если оно истинно, результатом становится выражение после знака ?, иначе — выражение после двоеточия. Вычисляется только одна из двух веток.
Оператор называют тернарным, потому что у него три операнда. В C++ он единственный такой, поэтому «тернарный оператор» и «условный оператор ?:» — одно и то же.
Первый пример
Найдём большее из двух чисел. Сначала через if ... else:
int max;
if (a > b) {
max = a;
} else {
max = b;
}
То же самое с тернарным оператором:
int max = a > b ? a : b;
Запись стала короче, а переменная получает значение сразу при объявлении.
Где он удобен
Инициализация константы
Константу нельзя сначала объявить, а потом присвоить ей значение в if. Тернарный оператор решает задачу в одну строку:
const int limit = isTest ? 10 : 1000;
Вывод на экран
std::cout << "Число " << (n % 2 == 0 ? "чётное" : "нечётное") << '\n';
Возврат из функции
int absolute(int x) {
return x < 0 ? -x : x;
}
Аргумент функции
printPrice(price, hasDiscount ? 0.9 : 1.0);
Во всех этих местах нужен результат-значение. Обычный if значения не даёт, поэтому без тернарного оператора пришлось бы заводить лишнюю переменную.
Скобки при выводе
У оператора ?: очень низкий приоритет — ниже, чем у сравнений, арифметики и оператора вывода <<. Поэтому в std::cout тернарное выражение нужно брать в скобки.
std::cout << a > b ? a : b; // ошибка компиляции
std::cout << (a > b ? a : b); // правильно
Без скобок компилятор читает строку как (std::cout << a) > b ? a : b: сначала выводит a, а потом пытается сравнить поток вывода с числом. Такого сравнения не существует, и программа не собирается.
Какого типа результат
У тернарного выражения один тип, и он должен подходить обеим веткам. Если ветки разного типа, компилятор приводит их к общему.
auto value = flag ? 1 : 2.5; // тип double: единица станет 1.0
Здесь int и double приводятся к double, поэтому при flag == true переменная получит 1.0, а не 1.
Если общего типа нет, программа не скомпилируется:
auto answer = flag ? 1 : "один"; // ошибка: int и строка несовместимы
Вложенные тернарные операторы
Тернарные операторы можно вкладывать, чтобы выбрать из трёх и более вариантов:
std::string grade = score >= 90 ? "отлично"
: score >= 70 ? "хорошо"
: score >= 50 ? "удовлетворительно"
: "неудовлетворительно";
Запись читается сверху вниз, как таблица: первое выполненное условие определяет ответ. В таком виде вложенность ещё понятна. Если же записать всё в одну строку или вложить оператор в ветку «истина», код превращается в головоломку:
int result = a > b ? a > c ? a : c : b > c ? b : c; // так писать не стоит
В этом случае лучше вернуться к if ... else if или вынести выбор в отдельную функцию.
Тернарный оператор или if-else
| Ситуация | Что выбрать |
|---|---|
| Нужно выбрать одно из двух значений | тернарный оператор |
Инициализируется const или ссылка | тернарный оператор |
| В ветках выполняются действия: вывод, вызовы, несколько строк | if ... else |
| Вариантов больше трёх | if ... else if или switch |
| Условие и ветки не помещаются в одну строку | if ... else |
Правило простое: тернарный оператор отвечает на вопрос «какое значение?», а if — на вопрос «что сделать?».
Что ещё полезно знать
Вычисляется только одна ветка. В выражении ptr != nullptr ? ptr->size : 0 обращение к ptr->size не произойдёт, если указатель нулевой.
Результату можно присваивать. Если обе ветки — переменные одного типа, тернарное выражение обозначает саму переменную, а не её копию:
(a > b ? a : b) = 0; // обнулит большую из двух переменных
В ветке может стоять throw. Так удобно проверять аргументы:
int size = n > 0 ? n : throw std::invalid_argument("n должно быть положительным");
Частые ошибки
- Нет скобок в
std::cout. Из-за низкого приоритета выражение разбирается не так, как задумано. - Ветки разного типа. Результат неожиданно становится
double, или код не компилируется. - Действия вместо значений. Запись
x > 0 ? print(x) : print(-x);работает, ноif ... elseздесь понятнее. - Глубокая вложенность. Три условия в одной строке никто не прочитает с первого раза, включая автора через месяц.
- Путаница с оператором
?из других языков. В C++ нет оператора??и сокращённой записиa ?: b— второй вариант существует только как расширение некоторых компиляторов.
Коротко
условие ? a : bдаётa, если условие истинно, иb, если ложно.- Это выражение со значением, поэтому оно подходит для инициализации, вывода и
return. - Внутри других выражений берите его в скобки.
- Обе ветки должны приводиться к одному типу.
- Для действий и длинных условий используйте
if ... else.
Остальные условные конструкции — if, else if и switch — разобраны в уроке Условные конструкции в C++. Отдельно про выбор из многих вариантов читайте в статье Оператор switch в C++.
Использованная литература
- Conditional operator — cppreference.com [Электронный ресурс]. — URL: https://en.cppreference.com/w/cpp/language/operator_other#Conditional_operator (дата обращения: 08.10.2026).
- ISO/IEC 14882:2024 — Язык программирования C++ [Электронный ресурс]. — URL: https://www.iso.org/standard/83626.html (дата обращения: 08.10.2026).