C ++ полагаться на неявное преобразование в bool в условиях? - PullRequest
6 голосов
/ 26 августа 2009

Я нашел следующее правило в листе стандартов кодирования :

Не полагайтесь на неявное преобразование в bool в условиях.

if (ptr) // неправильно

if (ptr! = NULL) // ok

Насколько разумно / полезно это правило?

Сколько перегрузок на скомпилированном коде?

Ответы [ 9 ]

11 голосов
/ 26 августа 2009

В самом строгом смысле вы можете положиться на неявные преобразования в bool. Обратная совместимость с C требует этого.

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

5 голосов
/ 26 августа 2009

Это правило ставит вас в тупик, если вы когда-нибудь захотите использовать класс, который имеет неявное преобразование в bool, например std::istream. Этот код читает слово из файла за раз, пока не будет достигнут EOF:

std::ifstream file("foo.txt");
std::string word;

while (file >> word)
{
    // do stuff
}

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

Для типов указателей это не имеет большого значения. Компилятор, вероятно, выдаст примерно такой же код для неявного преобразования в bool и явного теста против NULL. Это вопрос вкуса - ни один из них не «лучше» в абсолютном смысле. Стандарт кодирования просто пытается обеспечить согласованный стиль.

Имея это в виду, вы должны строго соблюдать стандарт кодирования при работе со встроенными типами (указатели, целые и т. Д.). Если вы столкнетесь с ситуацией, аналогичной приведенной выше, с классом, имеющим законное преобразование в bool, я бы поднял проблему с вашими товарищами по команде.

5 голосов
/ 26 августа 2009

В большинстве случаев это не ужасно, но может быть более читабельным, если вы введете именно то, что имеете в виду.

3 голосов
/ 29 апреля 2018

Я хотел добавить исторический взгляд на этот вопрос.

ANSI C (он же C89 / C90) был первой формальной спецификацией для C. Наряду с K & R C вы могли бы заметить нечто странное - понятия булева не существует. Операторы потока управления работают с выражениями , и их поток определяется на основе того, оценивается ли выражение как 0 или нет. Отсутствие логического типа является одним из самых больших упущений в C. Только в C99 C получил тип _Bool и определил макросы для bool, true и false в . stdbool.h (обратите внимание, они все еще целые числа). Аналогично, C ++ изначально не имел логического типа, получая его в C ++ 98 с bool.

Вот почему существуют неявные преобразования в логические значения. На мой взгляд, продолжать полагаться на этот плохой дизайн - логические значения были добавлены по причине. true всегда должно равняться true, и неявное преобразование всех ненулевых значений в true является неудовлетворительным.

NULL также является просто макросом, равным нулю, поэтому, в частности, для указателей в C ++ 11 вы должны использовать nullptr, чтобы определить, равен ли указатель нулю.

if(ptr != nullptr)
{
    // Do something with ptr.
}
1 голос
/ 26 августа 2009

Иногда я думаю, что это правило может быть нарушено, например, когда работа со стандартными библиотеками, которые возвращают int вместо bool (для совместимости с C89).

Однако это правило обычно приводит к более простому для понимания коду. Он даже применяется в таких языках, как C #, и в нем не слишком много жалоб, поэтому нет никаких серьезных недостатков в следовании этому правилу, кроме необходимости привыкнуть к нему.

1 голос
/ 26 августа 2009

Это никак не повлияет на скомпилированный код.

Что касается того, насколько это полезно - это, безусловно, поможет пониманию людей, пришедших из таких языков, как Java / C #. Это сделает более явным то, что вы проверяете. Будет выдано предупреждение, если вы начнете сравнивать целые числа с NULL (и тем самым укажете, что вы не уверены в типе рассматриваемой переменной). Я лично предпочитаю первую форму, но это не совсем необоснованное требование.

0 голосов
/ 26 августа 2009

Это впечатляюще глупое правило.

if (ptr != NULL) // ok

тогда почему бы не

 if ((ptr != NULL)==true) 
0 голосов
/ 26 августа 2009

Мне очень не нравится это правило. В C ++ нелогично использовать неявное преобразование в bool для типов указателей (и, конечно, для логических типов). ИМО, намного легче читать

bool conditionMet = false;

while (!conditionMet) // read as "while condition is not met"
{
    /* do something */
}

чем читать это:

bool conditionMet = false;

while (conditionMet == false) // read as "while conditionMet is false"
{
    /* do something */
}

То же самое для указателей. Кроме того, вводя ненужное сравнение, вы вводите еще одну возможность неправильно набирать номер и в конечном итоге получаете сравнение вместо сравнения, что, конечно, приведет к нежелательным результатам. В случаях, когда вы используете int как bool, как в старом C-коде, я думаю, вам также следует использовать неявное преобразование в bool.

0 голосов
/ 26 августа 2009

Правило, которое добавляет нулевую выгоду - это правило, которое вы можете выгодно удалить.

...