Question

Y at-il un « très mauvaise chose » qui peut se produire && = et || = ont été utilisés comme syntaxique sucre pour bool foo = foo && bar et bool foo = foo || bar?

Était-ce utile?

La solution

A bool ne peut être true ou false en C ++. En tant que tel, en utilisant &= et |= est relativement sûr (même si je ne aime pas particulièrement la notation). Certes, ils effectuent des opérations de bits plutôt que des opérations logiques (et donc ils ne seront pas de court-circuit), mais ces opérations de bits suivre une cartographie bien définie, ce qui est effectivement équivalent aux opérations logiques, aussi longtemps comme les deux opérandes sont de type bool . 1

Contrairement à ce que les autres ont dit ici, un bool en C ++ ne doit jamais avoir une valeur différente, comme 2. Lors de l'attribution de cette valeur à un bool, il sera converti en true selon la norme.

La seule façon d'obtenir une valeur non valide dans un bool est en utilisant reinterpret_cast sur les pointeurs:

int i = 2;
bool b = *reinterpret_cast<bool*>(&i);
b |= true; // MAY yield 3 (but doesn’t on my PC!)

Mais puisque ce code entraîne un comportement non défini de toute façon, nous pouvons ignorer en toute sécurité ce problème potentiel en se conformant code C ++.


1 Il est vrai que cela est une mise en garde plutôt grand que le commentaire de Angew illustre:

bool b = true;
b &= 2; // yields `false`.

La raison en est que b & 2 effectue promotion entier tel que l'expression est alors équivalente à static_cast<int>(b) & 2, qui se traduit par 0, qui est ensuite reconverti en un bool. Il est donc vrai que l'existence d'un operator &&= améliorerait la sécurité de type.

Autres conseils

&& et & ont une sémantique différente: && n'évaluera le second opérande si le premier opérande est false. à-dire quelque chose comme

flag = (ptr != NULL) && (ptr->member > 3);

est sûr, mais

flag = (ptr != NULL) & (ptr->member > 3);

n'est pas, bien que les deux opérandes sont de type bool.

La même chose est vraie pour &= et |=:

flag = CheckFileExists();
flag = flag && CheckFileReadable();
flag = flag && CheckFileContents();

se comportera différemment:

flag = CheckFileExists();
flag &= CheckFileReadable();
flag &= CheckFileContents();

Réponse courte

Tous les += opérateurs, -=, *=, /=, &=, |= ... sont l'arithmétique et de fournir même attente:

x &= foo()  // We expect foo() be called whatever the value of x

Toutefois, les opérateurs &&= et ||= serait logique, et ces opérateurs pourraient être sujettes à erreur, car de nombreux développeurs s'attendent foo() toujours être appelé x &&= foo().

bool x;
// ...
x &&= foo();           // Many developers might be confused
x = x && foo();        // Still confusing but correct
x = x ? foo() : x;     // Understandable
x = x ? foo() : false; // Understandable
if (x) x = foo();      // Obvious
  • Avons-nous vraiment besoin de faire C / C ++ encore plus complexe pour obtenir un raccourci pour x = x && foo()?

  • Voulons-nous vraiment plus obscurcir la déclaration sibylline x = x && foo()?
    Ou est-ce que nous voulons écrire du code comme significatif if (x) x = foo();?


Réponse longue

Exemple pour &&=

Si l'opérateur de &&= était disponible, ce code:

bool ok = true; //becomes false when at least a function returns false
ok &&= f1();
ok &&= f2(); //we may expect f2() is called whatever the f1() returned value

est équivalent à:

bool ok = true;
if (ok) ok = f1();
if (ok) ok = f2(); //f2() is called only when f1() returns true

Ce premier code est sujettes à l'erreur parce que de nombreux développeurs pensent f2() est toujours appelé quelle que soit la valeur renvoyée f1(). Il est comme écrire bool ok = f1() && f2();f2() est appelée que lorsque f1() retourne true.

  • Si le développeur veut réellement f2() être appelé que lorsque f1() retourne true donc le second code ci-dessus est moins sujette aux erreurs.
  • Else (le développeur veut f2() être toujours appelé), &= suffit:

Exemple pour &=

bool ok = true;
ok &= f1();
ok &= f2(); //f2() always called whatever the f1() returned value

En outre, il est plus facile pour le compilateur pour optimiser le code ci-dessus que ci-dessous une:

bool ok = true;
if (!f1())  ok = false;
if (!f2())  ok = false;  //f2() always called

Comparez && et &

On peut se demander si les opérateurs && et & donnent le même résultat lorsqu'il est appliqué sur les valeurs bool?

chèque Soit en utilisant le code C ++ suivant:

#include <iostream>

void test (int testnumber, bool a, bool b)
{
   std::cout << testnumber <<") a="<< a <<" and b="<< b <<"\n"
                "a && b = "<< (a && b)  <<"\n"
                "a &  b = "<< (a &  b)  <<"\n"
                "======================"  "\n";
}

int main ()
{
    test (1, true,  true);
    test (2, true,  false);
    test (3, false, false);
    test (4, false, true);
}

Sortie:

1) a=1 and b=1
a && b = 1
a &  b = 1
======================
2) a=1 and b=0
a && b = 0
a &  b = 0
======================
3) a=0 and b=0
a && b = 0
a &  b = 0
======================
4) a=0 and b=1
a && b = 0
a &  b = 0
======================

Conclusion

Par conséquent YES nous pouvons remplacer && par & pour des valeurs bool de
Donc, une meilleure utilisation &= au lieu de &&=.
On peut considérer &&= comme inutile pour booléens.

Idem pour ||=

  

|= de l'opérateur est également moins sujettes à erreur que ||=

Si un développeur veut f2() être appelé que lorsque f1() retourne false, au lieu de:

bool ok = false;
ok ||= f1();
ok ||= f2(); //f2() is called only when f1() returns false
ok ||= f3(); //f3() is called only when f1() or f2() return false
ok ||= f4(); //f4() is called only when ...

Je conseille l'alternative suivante plus compréhensible:

bool ok = false;
if (!ok) ok = f1();
if (!ok) ok = f2();
if (!ok) ok = f3();
if (!ok) ok = f4();
// no comment required here (code is enough understandable)

ou si vous préférez en une seule ligne style:

// this comment is required to explain to developers that 
// f2() is called only when f1() returns false, and so on...
bool ok = f1() || f2() || f3() || f4();
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top