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?

351voto

Michael Burr Punkte 320591

Das Argument, dass, wenn der Compiler einen Standard-Kopierkonstruktor bereitstellen kann, er auch in der Lage sein sollte, einen ähnlichen Standard operator==() macht ein gewisses Maß an Sinn. Ich denke, dass der Grund für die Entscheidung, keine vom Compiler erzeugte Voreinstellung für diesen Operator bereitzustellen, aus dem zu erraten ist, was Stroustrup in "The Design and Evolution of C++" (Abschnitt 11.4.1 - Control of Copying) über den Standard-Kopierkonstruktor gesagt hat:

Ich persönlich halte es für unglücklich dass die Kopiervorgänge Standard sind und ich verbiete das Kopieren von Objekten vieler meiner Klassen. Allerdings hat C++ seine Standard Zuweisungs- und Kopierkonstruktoren von C geerbt, und sie werden häufig verwendet.

Anstelle von "Warum hat C++ keinen Standard operator==() Die Antwort lautet: Diese Elemente wurden von Stroustrup widerwillig aufgenommen, um die Abwärtskompatibilität mit C zu gewährleisten (wahrscheinlich die Ursache für die meisten Fehler von C++, aber auch der Hauptgrund für die Popularität von C++).

Für meine eigenen Zwecke enthält das Snippet, das ich für neue Klassen verwende, in meiner IDE Deklarationen für einen privaten Zuweisungsoperator und einen Kopierkonstruktor, so dass ich beim Erstellen einer neuen Klasse keine Standardzuweisungs- und Kopieroperationen erhalte - ich muss die Deklaration dieser Operationen explizit aus der private: Abschnitt, wenn ich möchte, dass der Compiler sie für mich generieren kann.

139voto

Anton Savin Punkte 39432

Selbst in C++20 generiert der Compiler noch immer nicht implizit operator== für Sie

struct foo
{
    std::string str;
    int n;
};

assert(foo{"Anton", 1} == foo{"Anton", 1}); // ill-formed

Aber Sie werden die Fähigkeit erlangen ausdrücklich Standard == seit C++20 :

struct foo
{
    std::string str;
    int n;

    // either member form
    bool operator==(foo const&) const = default;
    // ... or friend form
    friend bool operator==(foo const&, foo const&) = default;
};

Verzug == tut Mitglied-weise == (auf die gleiche Weise, wie der Standard-Kopierkonstruktor eine mitgliederweise Kopierkonstruktion durchführt). Die neuen Regeln bieten auch die erwartete Beziehung zwischen == y != . Mit der obigen Erklärung kann ich zum Beispiel beides schreiben:

assert(foo{"Anton", 1} == foo{"Anton", 1}); // ok!
assert(foo{"Anton", 1} != foo{"Anton", 2}); // ok!

Diese spezielle Funktion (Standardeinstellung operator== und Symmetrie zwischen == y != ) kommt von ein Vorschlag das Teil des umfassenderen Sprachmerkmals war, das operator<=> .

82voto

Mark Ingram Punkte 68414

Der Compiler wüsste nicht, ob Sie einen Zeigervergleich oder einen tiefen (internen) Vergleich wünschen.

Es ist sicherer, es einfach nicht zu implementieren und den Programmierer das selbst machen zu lassen. Dann können sie alle Annahmen machen, die sie wollen.

48voto

alexk7 Punkte 2461

IMHO gibt es keinen "guten" Grund. Der Grund, warum so viele Menschen mit dieser Designentscheidung einverstanden sind, ist, dass sie nicht gelernt haben, die Macht der wertbasierten Semantik zu beherrschen. Die Leute müssen eine Menge benutzerdefinierter Kopierkonstruktoren, Vergleichsoperatoren und Destruktoren schreiben, weil sie rohe Zeiger in ihrer Implementierung verwenden.

Bei Verwendung geeigneter intelligenter Zeiger (wie std::shared_ptr) ist der Standard-Kopierkonstruktor in der Regel in Ordnung und die offensichtliche Implementierung des hypothetischen Standard-Vergleichsoperators wäre ebenso in Ordnung.

45voto

Rio Wing Punkte 612

Die Antwort lautet: C++ hat == nicht, weil C es nicht getan hat, und das ist der Grund, warum C nur standardmäßig =, aber kein == anbietet. C wollte es einfach halten: C hat = durch memcpy implementiert, aber == kann wegen des Auffüllens nicht durch memcmp implementiert werden. Da padding nicht initialisiert ist, sagt memcmp, dass sie unterschiedlich sind, obwohl sie gleich sind. Das gleiche Problem besteht bei leeren Klassen: memcmp sagt, sie seien unterschiedlich, weil die Größe leerer Klassen nicht Null ist. Wie oben zu sehen ist, ist die Implementierung von == komplizierter als die Implementierung von = in C. Einige Codes Beispiel Diesbezüglich. Wir freuen uns über Ihre Korrektur, falls ich falsch liege.

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