Warum bedeutet operator = return * das?

7

Sagen wir, ich möchte operator = überschreiben, damit ich etwas wie

machen kann %Vor%

Dann habe ich in meiner Implementierung von operator = etwas in der Art:

%Vor%

Machen Sie sich nichts vor der Implementierung, es funktioniert bereits.

Mein Problem ist, dass was passiert, wenn Sie return *this ? Ich weiß, dass es einen Verweis auf das Objekt gibt, aber ist das was passiert?

%Vor%     
Jude Maranga 02.01.2016, 05:19
quelle

5 Antworten

13

Sie return *this , damit Sie normale zusammengesetzte C ++ = -Anweisungen schreiben können wie:

%Vor%

weil diese Aussage grundsätzlich lautet:

%Vor%

Wenn p2.operator=(...) nicht return *this hätte, hättest du nichts Sinnvolles an p3.operator=(...) weitergeben können.

    
Paul Evans 02.01.2016, 05:22
quelle
5

p2 = p1 ist eine Abkürzung für p2.operator=(p1) . Es ruft nur Ihre Funktion operator= auf, die einen Verweis auf p2 zurückgibt, den Sie dann ignorieren. Um dies deutlich zu machen, nennen wir es assign anstelle von operator= :

%Vor%

Jetzt würden Sie anstelle von p2 = p1 schreiben

%Vor%

In diesem Fall wird das Ergebnis von assign ignoriert, aber Sie müssen es nicht ignorieren. Zum Beispiel könnten Sie schreiben:

%Vor%

Mit operator= anstelle von assign wird

%Vor%

Da die Zuweisung jedoch rechtsassoziativ ist, kann dies auch als

geschrieben werden %Vor%

Diese Form, mehrere Aufgaben gleichzeitig ausführen zu können, stammt ursprünglich von C und wurde in C ++ durch die Konvention von *this in operator=() beibehalten.

    
Vaughn Cato 02.01.2016 05:28
quelle
4

Man könnte versucht sein, den Kopierzuweisungsoperator dazu zu bringen, void zurückzugeben, wenn Sie sowieso keine verketteten Zuweisungen benötigen (wie in den anderen Antworten gezeigt). Schließlich sind verkettete Aufgaben oft schwer zu lesen und zu verstehen, so dass sie nicht als eine Verbesserung betrachtet werden können.

Ein oft übersehener Aspekt ist jedoch, dass void operator=(Poly& const) bedeutet, dass Ihr Typ die nicht mehr erfüllt CopyAssignable concept , das einen T& Rückgabetyp erfordert.

Ein Typ, der das CopyAssignable -Konzept nicht erfüllt, kann nicht offiziell für einige Standard-Container-Operationen verwendet werden, zum Beispiel std::vector::insert , was bedeutet, dass das folgende scheinbar unschuldige Stück Code undefiniertes Verhalten ergibt, obwohl es wahrscheinlich läuft völlig in Ordnung:

%Vor%

Wie der C ++ - Standard in § 17.6.4.8/2.3 erläutert, spricht er von Einschränkungen bei Programmen, die die Standardbibliothek verwenden:

  

(...) In den folgenden Fällen sind die Effekte undefined :

     

(...) für Typen, die bei der Instantiierung von a als Vorlagenargumente verwendet werden   Template-Komponente, wenn die Operationen auf dem Typ nicht das implementieren   Semantik der zutreffenden Anforderungen (...).

Natürlich ist es genau weil des undefinierten Verhaltens, dass ein Compiler den Fehler ignorieren darf und das Programm sich so verhält, dass er dem offensichtlich beabsichtigten Verhalten entspricht. Aber das ist nicht nötig.

Sie sollten auch berücksichtigen, dass Sie nicht alle zukünftigen Verwendungen Ihres Poly -Typs vorhersagen können. Jemand könnte eine Template-Funktion schreiben wie:

%Vor%

Diese Funktion würde dann nicht mit Ihrer Poly -Klasse funktionieren.

Verstoßen Sie einfach nicht gegen diese C ++ - Konvention und Sie werden keine Probleme bekommen.

    
Christian Hackl 02.01.2016 13:02
quelle
2
  

Was passiert, wenn Sie * das zurückgeben?

In Ihrem Beispiel ( p2 = p1; ) nichts. Die Methode kopiert p1 in p2 und gibt einen Verweis auf das Objekt 'this' zurück, das der aufrufende Code nicht verwendet.

In Code wie p3 = p2 = p1; ist der erste Aufruf p2 = p1 , der p1 in p2 kopiert und einen Verweis auf p2 zurückgibt. Der aufrufende Code kopiert dann von dieser Referenz zu p2 in p3 (und ignoriert den Verweis auf p3 , der zurückgegeben wird).

(Nebenbei: Stellen Ihre Unit-Tests sicher, dass p1 = p1 ordnungsgemäß funktioniert? Diesen Fall können Sie leicht vergessen!)

    
Toby Speight 07.01.2016 17:52
quelle
0

Das Zurückgeben eines Verweises auf das Zielobjekt erlaubt das Zuweisen von Verkettungen (Kaskaden) und das Überladen von Operatoren innerhalb einer Klasse folgt rechtsassoziativ (klicken Sie auf hier für detaillierte Regeln zum Überladen von Operatoren)

%Vor%     
Junyu Zhou 02.01.2016 05:38
quelle