Ответ 1
Тернарный оператор эффективно работает следующим образом:
std::string str = "test";
std::string _; // using _ since you don't store the variable
if (str == "tes") {
_ = str.replace(0, 1, "T");
} else {
_ = 0; // this calls std::string(nullptr);
}
В приведенном выше случае вы не храните значение, но необходимо отметить несколько условий:
- И истинный случай, и ложный случай должны быть одного типа (или быть конвертируемыми в один и тот же тип).
- Он по-прежнему работает, даже если тип не имеет конструктора по умолчанию (поэтому он более сложный, чем выше).
Проблема в том, что ваш код ожидает, что тип будет std::string
, в зависимости от типа в истинном случае. Тип в ложном случае является литералом, литералом, который можно считать эквивалентным NULL
, и поэтому его можно считать a const char*
, который можно конвертировать в std::string
. Если вы попытаетесь построить std::string
из nullptr, он выдает исключение выше.
Это на самом деле довольно тонко, поскольку, если вы используете любой целочисленный литерал, отличный от 0, компилятор выдает ошибку:
#include <string>
int main()
{
std::string s(0); // 0 is comparable to NULL
// std::string s1(1); // compiler error: no constructor found
return 0;
}
Будьте осторожны с неявными преобразованиями. Ошибка нулевой проверки и времени выполнения довольно изящна и впоследствии избавила вас от тонких ошибок или сбоев (почти наверняка segfault).