367 Stimmen

Warum definieren C++-Compiler nicht operator== und operator!=?

Ich bin ein großer Fan davon, den Compiler so viel Arbeit wie möglich für Sie erledigen zu lassen. Wenn Sie eine einfache Klasse schreiben, kann der Compiler Ihnen das Folgende "kostenlos" zur Verfügung stellen:

  • Ein (leerer) Standardkonstruktor
  • Ein Kopierkonstruktor
  • Ein Destruktor
  • Ein Zuweisungsoperator ( operator= )

Aber es scheint keine Vergleichsoperatoren zu geben - wie zum Beispiel operator== o operator!= . Zum Beispiel:

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
{ }

Gibt es dafür einen guten Grund? Warum sollte die Durchführung eines mitgliederbezogenen Vergleichs ein Problem darstellen? Wenn die Klasse Speicher zuweist, sollte man natürlich vorsichtig sein, aber bei einer einfachen Klasse könnte der Compiler dies doch sicher für Sie erledigen?

37voto

Nikos Athanasiou Punkte 26657

In diesem Video Alex Stepanov, der Erfinder von STL, geht auf diese Frage etwa um 13:00 Uhr ein. Zusammengefasst argumentiert er, nachdem er die Entwicklung von C++ beobachtet hat, dass:

  • Es ist bedauerlich, dass \== und != nicht implizit erklärt werden (und Bjarne stimmt ihm zu). Eine korrekte Sprache sollte diese Dinge für Sie bereithalten (er geht noch weiter und schlägt vor, dass Sie nicht in der Lage sein sollten, eine != die die Semantik von \== )
  • Der Grund dafür, dass dies der Fall ist, hat seine Wurzeln (wie viele der C++-Probleme) in C. Dort ist der Zuweisungsoperator implizit definiert mit Bit-für-Bit-Zuweisung aber das würde nicht funktionieren für \== . Eine ausführlichere Erklärung finden Sie in diesem Artikel von Bjarne Stroustrup.
  • In der anschließenden Frage Warum wurde dann nicht ein Vergleich der einzelnen Mitglieder vorgenommen? er sagt ein tolle Sache : C war eine Art selbstentwickelte Sprache, und der Typ, der diese Dinge für Ritchie implementierte, sagte ihm, dass er es schwierig fand, dies zu implementieren!

Er sagt dann, dass in der (fernen) Zukunft \== y != wird implizit erzeugt.

25voto

VLL Punkte 8491

C++20 bietet eine Möglichkeit, einen Standard-Vergleichsoperator einfach zu implementieren.

Beispiel aus cppreference.com :

class Point {
    int x;
    int y;
public:
    auto operator<=>(const Point&) const = default;
    // ... non-comparison functions ...
};

// compiler implicitly declares operator== and all four relational operators work
Point pt1, pt2;
if (pt1 == pt2) { /*...*/ } // ok, calls implicit Point::operator==
std::set<Point> s; // ok
s.insert(pt1); // ok
if (pt1 <= pt2) { /*...*/ } // ok, makes only a single call to Point::operator<=>

16voto

sergtk Punkte 10154

Es ist nicht möglich, Standardwerte zu definieren == aber Sie können Standardwerte definieren != über == die Sie normalerweise selbst definieren sollten. Hierfür sollten Sie folgende Dinge tun:

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

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

Sie können sehen http://www.cplusplus.com/reference/std/utility/rel_ops/ für Details.

Wenn Sie darüber hinaus definieren operator< können die Operatoren für <=, >, >= daraus abgeleitet werden, wenn man std::rel_ops .

Aber Sie sollten vorsichtig sein, wenn Sie die std::rel_ops weil Vergleichsoperatoren für die Typen abgeleitet werden können, für die sie nicht erwartet werden.

Die bevorzugte Methode zur Ableitung des verwandten Operators aus dem Basisoperator ist die Verwendung von boost::Operatoren .

Der in boost verwendete Ansatz ist besser, weil er die Verwendung des Operators nur für die gewünschte Klasse und nicht für alle Klassen im Geltungsbereich definiert.

Sie können auch "+" aus "+=", "-" aus "-=" usw. erzeugen (siehe vollständige Liste). aquí )

11voto

MSalters Punkte 166675

C++0x hat hatte einen Vorschlag für Standardfunktionen, so dass man sagen konnte default operator==; Wir haben gelernt, dass es hilfreich ist, diese Dinge deutlich zu machen.

5voto

Paul de Vrieze Punkte 4851

Konzeptionell ist es nicht einfach, Gleichheit zu definieren. Selbst bei POD-Daten könnte man argumentieren, dass selbst wenn die Felder gleich sind, es sich aber um ein anderes Objekt (mit einer anderen Adresse) handelt, es nicht unbedingt gleich ist. Dies hängt tatsächlich von der Verwendung des Operators ab. Leider ist Ihr Compiler kein Hellseher und kann das nicht ableiten.

Außerdem sind Standardfunktionen eine hervorragende Möglichkeit, sich selbst ins Abseits zu stellen. Die von Ihnen beschriebenen Standardfunktionen sind im Wesentlichen dazu da, die Kompatibilität mit POD-Strukturen zu wahren. Sie verursachen jedoch mehr als genug Chaos, wenn Entwickler sie vergessen oder die Semantik der Standardimplementierungen vergessen.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X