Является !! безопасный способ конвертировать в bool в C ++? - PullRequest
49 голосов
/ 15 октября 2008

[Этот вопрос относится, но не совпадает с к этому .]

Если я пытаюсь использовать значения определенных типов в качестве логических выражений, я получаю предупреждение. Вместо того, чтобы подавить предупреждение, я иногда использую троичный оператор (?:) для преобразования в bool. Использование двух не операторов (!!), кажется, делает то же самое.

Вот что я имею в виду:

typedef long T;       // similar warning with void * or double
T t = 0;
bool b = t;           // performance warning: forcing 'long' value to 'bool'
b = t ? true : false; // ok
b = !!t;              // any different?

Итак, техника двойного отказа действительно делает то же самое? Это более или менее безопасно, чем троичная техника? Является ли этот метод одинаково безопасным для нецелых типов (например, с void * или double для T)?

Я не спрашиваю, является ли !!t хорошим стилем. Я спрашиваю, семантически ли он отличается от t ? true : false.

Ответы [ 17 ]

82 голосов
/ 16 октября 2008

аргумент! оператор и первый аргумент тернарного оператора неявно преобразуются в bool, так что !! и?: являются ли ИМО глупыми избыточными украшениями актерского состава. Я голосую за

b = (t != 0);

Нет неявных преобразований.

41 голосов
/ 15 октября 2008

В качестве альтернативы, вы можете сделать это: bool b = (t != 0)

31 голосов
/ 16 октября 2008

Осторожно!

  • Логическое выражение об истине и ложности.
  • Целое число около целых чисел.

Это очень разные понятия:

  • Правда и ложь - это решающие вещи.
  • Числа относятся к подсчету вещей.

При соединении этих понятий это следует делать явно. Мне больше нравится версия Димы:

b = (t != 0);

Этот код четко говорит: сравните два числа и сохраните значение истины в логическом значении.

6 голосов
/ 15 октября 2008


Да, это безопасно.


0 интерпретируется как ложное, все остальное верно,
следовательно! 5 выходит как ложное
! 0 выходит как правда
так !! 5 получается как правда

6 голосов
/ 15 октября 2008

Все допустимые методы, все будут генерировать один и тот же код.

Лично я просто отключаю предупреждение, чтобы использовать самый чистый синтаксис. Кастинг в bool - это не то, что я боюсь делать случайно.

5 голосов
/ 16 октября 2008

Я бы не использовал:

bool b = !!t;

Это наименее читаемый способ (и, следовательно, труднее всего поддерживать)

Остальные зависят от ситуации.
Если вы конвертируете для использования только в выражении bool.

bool b = t ? true : false;
if (b)
{
    doSomething();
}

Тогда я бы позволил языку сделать это для вас:

if (t)
{
    doSomething();
}

Если вы на самом деле храните логическое значение. Тогда сначала я бы удивился, почему у вас длинные места в первых местах, где требуется актерский состав. Предполагая, что вам нужны long и значение bool, я рассмотрю все следующее в зависимости от ситуации.

bool  b = t ? true : false;      // Short and too the point.
                                 // But not everybody groks this especially beginners.
bool  b = (t != 0);              // Gives the exact meaning of what you want to do.
bool  b = static_cast<bool>(t);  // Implies that t has no semantic meaning
                                 // except as a bool in this context.

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

3 голосов
/ 15 октября 2008

Я рекомендую никогда не подавлять это предупреждение и никогда не использовать c cast (bool) для его подавления. Преобразования не всегда могут быть вызваны, как вы предполагаете.

Существует разница между выражением, имеющим значение true, и логическим значением этого значения.

Оба !! и к троичному берутся привыкнуть, но будут делать то же самое, если не хотите определять внутренние типы с перегруженными приведениями к bool.

Подход Димы тоже подойдет, поскольку он присваивает значение выражения bool.

2 голосов
/ 16 октября 2008

Я действительно ненавижу !! т !!!!!! Это пахнет самой худшей вещью в C и C ++, соблазном быть слишком умным вдвое с вашим синтаксисом.

bool b (t! = 0); // ИМХО самый лучший способ, он явно показывает, что происходит.

2 голосов
/ 15 октября 2008

Если вас беспокоит предупреждение, вы также можете вызвать приведение: bool b = (bool)t;

1 голос
/ 15 октября 2008

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

...