Двойное отрицание в коде C ++ - PullRequest
109 голосов
/ 30 октября 2008

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

Я в основном имею дело с C ++, и большая часть кода, который они пишут, использует двойное отрицание для своей логической логики.

 if (!!variable && (!!api.lookup("some-string"))) {
       do_some_stuff();
 }                                   

Я знаю, что эти ребята - умные программисты, очевидно, что они не делают это случайно.

Я не опытный специалист по C ++, я могу только догадываться, почему они делают это, потому что они хотят быть абсолютно уверены, что оцениваемое значение является фактическим логическим представлением. Таким образом, они отрицают это, затем отрицают это снова, чтобы вернуть это к его фактическому логическому значению.

Это правильно, или я что-то упустил?

Ответы [ 14 ]

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

Как упоминалось Марчин , вполне может иметь значение, если перегрузка оператора находится в игре. В противном случае в C / C ++ это не имеет значения, за исключением случаев, когда вы делаете одну из следующих вещей:

  • прямое сравнение с true (или в C что-то вроде макроса TRUE), что почти всегда является плохой идеей. Например:

    if (api.lookup("some-string") == true) {...}

  • вы просто хотите что-то преобразовать в строгое значение 0/1. В C ++ присвоение bool будет делать это неявно (для тех вещей, которые неявно преобразуются в bool). В C или если вы имеете дело с переменной не-bool, это идиома, которую я видел, но я предпочитаю разнообразие (some_variable != 0).

Я думаю, что в контексте более крупного логического выражения оно просто загромождает вещи.

0 голосов
/ 12 октября 2016

Это может быть примером трюка двойного взрыва , для получения более подробной информации см. Safe Bool Idiom Здесь я подведу итоги первой страницы статьи.

В C ++ существует несколько способов предоставить логические тесты для классов.

Очевидным способом является operator bool оператор преобразования.

// operator bool version
  class Testable {
    bool ok_;
  public:
    explicit Testable(bool b=true):ok_(b) {}

    operator bool() const { // use bool conversion operator
      return ok_;
    }
  };

Мы можем проверить класс,

Testable test;
  if (test) 
    std::cout << "Yes, test is working!\n";
  else 
    std::cout << "No, test is not working!\n";

Однако opereator bool считается небезопасным, поскольку допускает бессмысленные операции, такие как test << 1; или int i=test.

Использование operator! безопаснее, поскольку мы избегаем проблем неявного преобразования или перегрузки.

Реализация тривиальна,

bool operator!() const { // use operator!
    return !ok_;
  }

Два идиоматических способа проверки Testable объекта:

  Testable test;
  if (!!test) 
    std::cout << "Yes, test is working!\n";
  if (!test2) {
    std::cout << "No, test2 is not working!\n";

Первая версия if (!!test) - это то, что некоторые люди называют трюком двойного взрыва .

0 голосов
/ 30 октября 2008

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

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

0 голосов
/ 30 октября 2008

Это правильно, но в C здесь бессмысленно - 'if' и '&&' будут относиться к выражению одинаково без '!!'.

Причина, по которой я делаю это в C ++, заключается в том, что '&&' может быть перегружено. Но тогда, как и «!», Это не значит, что действительно не гарантирует, что вы получите bool, не глядя на код для типов variable и api.call. Может быть, кто-то с большим опытом C ++ мог бы объяснить; возможно, это была мера глубокой защиты, а не гарантия.

...