333 votes

Pourquoi ne pas compilateurs C++ définir l'opérateur== et l'opérateur!=?

Je suis un grand fan de laisser le compilateur faire autant de travail pour vous que possible. Lors de l'écriture d'une simple classe, le compilateur peut vous donner la suite de "libre":

  • Une valeur par défaut (vide) constructeur
  • Un constructeur de copie
  • Un destructeur
  • Un opérateur d'affectation (operator=)

Mais il ne semble pas à vous donner tous les opérateurs de comparaison - comme operator== ou operator!=. Par exemple:

class foo
{
public:
    std::string str_;
    int n_;
};

foo f1;        // Works
foo f2(f1);    // Works
foo f3;
f3 = f2;       // Works

if (f3 == f2)  // Fails
{ }

if (f3 != f2)  // Fails
{ }

Est-il une bonne raison à cela? Pourquoi effectuer un membre par membre comparaison être un problème? Évidemment, si la classe alloue de la mémoire, alors vous voulez être prudent, mais pour une classe simple, sûrement, le compilateur pourrait le faire pour vous?

332voto

Michael Burr Points 181287

L'argument que si le compilateur peut fournir un constructeur de copie par défaut, il devrait être en mesure de fournir un similaire par défaut operator==() fait une certaine quantité de sens. Je pense que la raison de la décision de ne pas donner une générées par le compilateur par défaut pour cet opérateur peut être deviné par ce Stroustrup dit sur le constructeur de copie par défaut dans "La Conception et l'Évolution de C++" (Section 11.4.1 - Contrôle de la Copie):

Personnellement, je considère ça dommage que les opérations de copie sont définis par par défaut et j'ai interdire la copie de les objets de plusieurs de mes classes. Cependant, C++ hérité de son par défaut cession et copie des constructeurs de C, et ils sont fréquemment utilisés.

Ainsi, au lieu de "pourquoi ne pas en C++ par défaut est operator==()?", la question aurait du être "pourquoi est-ce que C++ ont une valeur par défaut de cession et de constructeur de copie?", la réponse pour le cours de ces éléments ont été inclus à contrecœur par Stroustrup pour la compatibilité ascendante avec C (probablement la cause de la plupart de C++de verrues, mais aussi sans doute la raison principale de C++de popularité).

Pour mes propres fins, dans mon IDE de l'extrait de code que j'utilise pour nouvelles classes contient des déclarations pour un opérateur d'affectation et de constructeur de copie, de sorte que lorsque j'ai gen en place d'une nouvelle classe je n'ai pas d'attribution par défaut et les opérations de copie - j'ai supprimer explicitement la déclaration de ces opérations à partir de l' private: section si je veux le compilateur pour être en mesure de générer pour moi.

79voto

Mark Ingram Points 24995

Le compilateur ne savais pas si tu voulais un pointeur de comparaison ou profonde (interne), de la comparaison.

Il est plus sûr de ne pas la mettre en œuvre et de permettre au programmeur de le faire eux-mêmes. Ensuite, ils peuvent faire toutes les hypothèses qu'ils aiment.

45voto

alexk7 Points 569

À mon humble avis, il n'y a pas de "bonne" raison. Pourquoi il y a tant de gens qui sont d'accord avec cette décision de conception est parce qu'ils n'ont pas appris à maîtriser le pouvoir de la valeur basée sur la sémantique. Les gens ont besoin d'écrire beaucoup de custom constructeur de copie, les opérateurs de comparaison et les destructeurs parce qu'ils utiliser des pointeurs dans leur mise en œuvre.

Lors de l'utilisation appropriée des pointeurs intelligents (comme boost::shared_ptr), le constructeur de copie par défaut est généralement fine et l'évidence de la mise en œuvre de l'hypothétique opérateur de comparaison par défaut serait aussi bien.

42voto

Rio Points 136

Il est répondu C++ n'est pas l' == parce que le C n'a pas, et voici pourquoi C par défaut = mais pas de == la première place. C voulait faire simple: C mise en œuvre = par memcpy; cependant, == ne peut pas être mis en œuvre par memcmp, en raison de rembourrage. Parce que le rembourrage n'est pas initialisé, memcmp dit qu'ils sont différents même s'ils sont les mêmes. Le même problème existe pour la classe vide: memcmp dit qu'ils sont différents en raison de la taille de vide classes ne sont pas à zéro. Il peut être vu à partir de ci-dessus que la mise en œuvre == est plus compliqué que de mettre en place = C. Un peu de code exemple à ce sujet. Votre correction est apprécié si je me trompe.

16voto

sergtk Points 3109

Il n'est pas possible de définir par défaut ==, mais vous pouvez définir une valeur par défaut != par == qui d'habitude vous devez définir vous-mêmes. Pour cela, vous devez faire les choses suivantes:

#include <utility>
using namespace std::rel_ops;
...

class FooClass
{
public:
  bool operator== (const FooClass& other) const {
  // ...
  }
};

Vous pouvez voir http://www.cplusplus.com/reference/std/utility/rel_ops/ pour plus de détails.

En outre, si vous définissez operator< , les opérateurs <=, >, >= peut être déduit lors de l'utilisation d' std::rel_ops.

Mais vous devez être prudent lorsque vous utilisez std::rel_ops parce que les opérateurs de comparaison peuvent être déduits pour les types ne sont pas prévu pour.

Plus privilégiées de façon à en déduire liés à l'opérateur de base est d'utiliser boost::opérateurs.

L'approche utilisée dans boost est mieux parce que cela permet de définir l'utilisation de l'opérateur pour la classe que vous ne voulez, pas pour toutes les classes de la portée.

Vous pouvez également générer des "+" de "+=", - de "-=", etc... (voir la liste complète ici)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X