Ответ 1
Производительность
Тернарный оператор не должен отличаться по производительности от хорошо написанного эквивалентного оператора if
/else
... они могут хорошо разрешаться к одному и тому же представлению в абстрактном дереве синтаксиса, претерпевать такие же оптимизации и т.д.
Вещи, с которыми вы можете справиться?
Если вы инициализируете константу или ссылку или разрабатываете, какое значение использовать внутри списка инициализации члена, то операторы if
/else
не могут использоваться, но ?
:
может быть:
const int x = f() ? 10 : 2;
X::X() : n_(n > 0 ? 2 * n : 0) { }
Факторинг для краткого кода
Ключ к использованию ?
:
включает локализацию и исключает избыточное повторение других частей тех же операторов/вызовов функций, например:
if (condition)
return x;
else
return y;
... предпочтительнее...
return condition ? x : y;
... по соображениям удобочитаемости, если речь идет о очень неопытных программистах, или некоторые из этих терминов достаточно сложны, что структура ?
:
теряется в шуме. В более сложных случаях вроде:
fn(condition1 ? t1 : f1, condition2 ? t2 : f2, condition3 ? t3 : f3);
Эквивалент if
/else
:
if (condition1)
if (condition2)
if (condition3)
fn(t1, t2, t3);
else
fn(t1, t2, f3);
else if (condition3)
fn(t1, f2, t3);
else
fn(t1, f2, f3);
else
if (condition2)
...etc...
Это много дополнительных вызовов функций, которые компилятор может или не может оптимизировать.
Невозможно присвоить именам временного времени улучшение надстроек if/else выше?
Если выражения t1
, f1
, t2
и т.д. слишком многословны для повторного ввода, создание именованных временных файлов может помочь, но затем:
-
Чтобы получить соответствие производительности
?
:
, вам может понадобиться использоватьstd::move
, за исключением случаев, когда одно и то же временное передается двум параметрам&&
в вызываемой функции: тогда вы должны избегать этого. Это более сложный и подверженный ошибкам. -
c
?
x:
y оценивает c, то либо не оба x и y, что позволяет с уверенностью сказать, что для проверки указатель не являетсяnullptr
перед его использованием, предоставляя некоторое резервное значение/поведение. Код получает только побочные эффекты от x и y. С указанными временными параметрами вам может понадобитьсяif
/else
вокруг или?
:
внутри их инициализации на выполнение нежелательного кода или выполнение кода чаще, чем требуется.
Функциональная разница: унифицирующий тип результата
Рассмотрим:
void is(int) { std::cout << "int\n"; }
void is(double) { std::cout << "double\n"; }
void f(bool expr)
{
is(expr ? 1 : 2.0);
if (expr)
is(1);
else
is(2.0);
}
В версии условного оператора выше 1
претерпевает стандартное преобразование в double
, так что тип, сопоставленный 2.0
, что означает, что перегрузка is(double)
вызывается даже для ситуации true
/1
. Оператор if
/else
не вызывает это преобразование: ответные сообщения true
/1
is(int)
.
Вы также не можете использовать выражения с общим типом void
в условном операторе, тогда как они действительны в операторах под if
/else
.
Акцент: выбор значения до/после действия, требующего значений
Есть другой акцент:
Оператор if
/else
подчеркивает сначала ветвление, и что нужно сделать, является вторичным, в то время как троичный оператор подчеркивает, что делать с выбором значений, чтобы сделать это с.
В разных ситуациях либо может лучше отражать "естественный" взгляд программиста на код, а также упрощать его понимание, проверку и поддержку. Вы можете выбрать один из них на основе порядка, в котором вы учитываете эти факторы при написании кода - если вы запустили "что-то", то обнаружите, что вы можете использовать один из пары (или нескольких) значений он с ?
:
является наименее разрушительным способом выразить это и продолжить кодирование "поток".