Frage

Wenn ich eine Klasse habe, die viele hat int, float, und enum Mitgliedervariablen, wird es als effizient und/oder eine gute Praxis angesehen, sie eher als Referenzen als als Kopien zurückzugeben, und konstante Referenzen zurückzugeben, bei denen keine Änderungen vorgenommen werden sollten? Oder gibt es einen Grund, warum ich sie als Kopien zurückgeben sollte?

War es hilfreich?

Lösung

Es gibt keinen Grund, primitive Typen wie z. int und float Nach Bezugnahme, es sei denn, Sie möchten ihnen zulassen, dass sie geändert werden. Die Rückgabe durch Referenz ist tatsächlich weniger effizient, weil es nichts spart (intS und Zeiger haben normalerweise die gleiche Größe.

Andere Tipps

Wenn es sich um ständige Referenzen handelt, ist es vielleicht in Ordnung. Wenn sie keine ständigen Referenzen sind, wahrscheinlich nicht.

In Bezug auf Effizienz-auf einer 64-Bit-Maschine werden die Referenzen 64-Bit-Mengen (in Verkleidung) betragen. int und float und enum wird kleiner sein. Wenn Sie eine Referenz zurückgeben, erzwingen Sie eine Indirektion. Es ist weniger effizient.

Insbesondere für integrierte Typen als Rückgabewerte ist es im Allgemeinen besser, den Wert zurückzugeben als als Referenz.

Einige Fälle sind notwendig:

Schauen Sie sich überlastet an operator[] für jede Klasse. Es hat normalerweise zwei Versionen. Die mutierende Version muss eine Referenz zurückgeben.

int &operator[](int index);           // by reference
int operator[](int index) const;      // by value

Im Allgemeinen ist es in Ordnung, den Klassenmitgliedern durch vertrauenswürdige Unternehmen durch eine Klassenfreunde den Zugang zu den Klassenmitgliedern zu ermöglichen. Falls diese vertrauenswürdigen Unternehmen auch den Staat, Referenzen oder Zeiger an die Klassenmitglieder ändern müssen, sind die einzigen Optionen, die man hat.

In vielen Fällen vereinfachen Referenzen normalerweise die Syntax, z.

v.at(1) = 2 vs *(v.at(1)) = 2;

Dies ist wahrscheinlich meistens eine Frage von Stil oder Präferenz. Ein Grund, keine Referenzen zurückzugeben, ist, dass Sie Getter und Setter verwenden, um die Implementierung dieser Mitglieder zu ändern. Wenn Sie ein privates Mitglied in einen anderen Typ geändert haben, oder es vollständig entfernt, weil es berechnet werden kann, haben Sie nicht mehr Die Fähigkeit, eine Referenz zurückzugeben, da es nichts zu referenzieren gibt.

Auf der anderen Seite kann die Rückgabe von Referenzen für nicht-triviale Typen (zusammengesetzte Klassen) Ihren Code etwas über die Erstellung einer Kopie beschleunigen, und Sie können zulassen, dass diese Mitglieder über die zurückgegebene Referenz (falls gewünscht) zugewiesen werden.

Fast, Const Referenzen sind besser. Für INTs und solche sind keinen Sinn, weil Sie möchten, dass sie geändert werden oder weil sie die gleiche Größe (oder fast) wie eine Referenz haben.

Also ja, es ist eine gute Idee. Ich bevorzuge eine andere Sprache oder hackt mich in meinem eigenen C ++ - und erlaube einfach, dass der Var öffentlich ist (wieder einmal nur meine eigenen Sachen)

Dies ist meistens eine Leistungsfrage, aber aus Robustheitspunkt würde ich sagen, dass es vorzugsweise ist, Werte anstelle von Const Referenzen zurückzugeben. Der Grund dafür ist, dass sogar Const Referenzen die Kapselung schwächt. Bedenken Sie:

struct SomeClass
{
   std::vector<int> const & SomeInts () const;
   void AddAnInt (int i);  // Adds an integer to the vector of ints.
private:
   std::vector<int> m_someInts;
};

bool ShouldIAddThisInt(int i);

void F (SomeClass & sc)
{
   auto someInts = sc.SomeInts ();
   auto end = someInts.end ();
   for (auto iter = someInts.begin (); iter != end; ++iter)
   {
      if (ShouldIAddThisInt(*iter))
      {
         // oops invalidates the iterators
         sc.AddAnInt (*iter);
      }
   }  
}

Für den Fall, dass es semantisch sinnvoll ist und wir übermäßige dynamische Zuordnungen vermeiden können, bevorzuge ich die Rendite nach Wert.

Getters sind für Emissionen einer Klasse Say Say Exhaust Car.emit(), wo das Auto gerade das geschaffen hat Exhaust.

Wenn Sie verpflichtet sind zu schreiben const Seat& Car.get_front_seat()
Später in der sitzen zu lassen Driver, Sie können sofort bemerken, dass etwas nicht stimmt.
Korrecly, Sie möchten lieber schreiben Car.get_in_driver(Driver)
was dann direkt aufruft seat.sit_into(Driver).

Diese zweite Methode vermeidet diese unangenehmen Situationen leicht, wenn Sie get_front_seat Aber die Tür ist geschlossen und Sie drücken den Fahrer praktisch durch die geschlossene Tür. Denken Sie daran, Sie haben nur nach einem Platz gebeten! :)

Alles in allem: Immer nach Wert zurückgeben (und verlassen Sie sich auf die Optimierung der Rückgabewert) oder erkennen Sie, dass es Zeit ist, Ihr Design zu ändern.

Der Hintergrund: Klassen wurden erstellt, sodass Daten zusammen mit der Zubehörfunktion, der Lokalisierung von Fehler usw. gekoppelt werden können. Daher sind Klassen niemals Aktivität, sondern datenorientiert.

Weitere Fallstricke: In C ++ - Wenn Sie etwas von Const Ref zurückgeben, können Sie leicht vergessen, dass es sich nur um einen Schiedsrichter handelt und wenn Ihr Objekt zerstört wird, können Sie mit einem ungültigen Schiedsrichter hinterlassen werden. Ansonsten dieses Objekt wird kopiert Sobald es trotzdem den Gettter verlässt. Aber unnötige Kopien werden vom Compiler vermieden, siehe Rückgabewertoptimierung.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top