2016-04-01 14 views
4

zu übergeben Ich hatte einen Midterm in C++ und eine unserer Zuweisungen war eine Klasse zu schreiben, die den << Operator überlädt, so dass wir private Felder dieser Klasse std::ostream, wie so drucken könnten :Ist es obligatorisch, Klassen durch Referenz in C++

Crate c1(2600, 9500); 
Crate c2; 
cout << c1 << ", " << c2 << endl; 

hatte Crate weight: 2600 Crate value: 9500, Crate weight: 0 Crate value: 0

Meine Umsetzung war

class Crate { 
    int weight; 
    int value; 
public: 
    Crate():weight(0), value(0) {} 
    Crate (int w, int v); 
    Crate& operator+= (Crate& c); 
    int operator+= (int& w); 

    friend ostream& operator<< (ostream& out, Crate c) { 
     out << "Crate weight: " << c.weight; 
     out << " Crate value: " << c.value; 
     return out; 
    } 
}; 

jedoch zu drucken, ich hat 0/3 Punkte für den überladenen Operator << bekommen, und der einzige Unterschied zwischen meiner Lösung und der Bewertungsschablone war, dass ich Crate c nach Wert übertrage und sie als Referenz weitergegeben habe.

Wenn die Klasse dynamisch Elementvariablen zugewiesen hätte, müsste ich natürlich Instanzen davon als Referenz übergeben, aber das ist hier nicht der Fall.

Ich weiß, dass das Beispiel cppreference.com eine const-Referenz verwendet, aber gibt es eine strikte Regel, dass man eine const-Referenz verwenden muss, wenn Sie dies tun?

Ich verstehe, dass meine Lösung Kopien sowohl weight und value auf den Stapel statt nur einen Zeiger auf das Objekt zu kopieren, aber 4 Bytes ist (im Fall eines 32-Bit-Systems) auf dem Stack wirklich so viel von einem Problem oder fehlt mir etwas viel Ernsteres (wie ein Speicherleck)?

Ich überprüfte auch die Demontage beider Lösungen, aber ich konnte nichts finden, was meine Lösung Null Punkte wert wäre.

Ich habe auch meine Professoren gefragt, aber sie fingen an, darüber zu sprechen, es als const zu übergeben, aber ich sehe nicht, wie das diese Lösung in Bezug auf Arbeiten besser machen würde/nicht funktioniert. Ein anderer Professor sagte mir, dass "das syntaktisch völlig falsch ist". aber es kompiliert mit Visual Studio und MinGW, so kann ich auch keinen Sinn machen.

Bitte beachten Sie auch, dass dies ein Kurs für Elektroingenieure ist.

+0

Ich weiß nicht, ob ich damit einverstanden bin, dass es wert 0 ist, aber die Faustregel, die ich immer gehört habe, ist, wenn der Typ größer ist als sein Zeiger (im Grunde jedes nicht-primitive), durch Verweis gehen, und es sollte immer const sein, außer du brauchst unbedingt die Fähigkeit, es zu modifizieren. – Carcigenicate

+0

@Carcigenicate 'struct Cls {int i; }; '=>' sizeof (Cls)

+0

Ich weiß, dass das Überladen des Operators erfordert, dass der Iterationsparameter const ist. Allerdings sind diese Arten von technischen Details meines Wissens nicht bekannt. Hier ist eine Erklärung, die helfen könnte: http://StackOverflow.com/a/2828320/4775223 –

Antwort

5

Ist es obligatorisch Klassen durch Verweis in c passieren ++

Nr

„als const Passing“, die nur dumm ist, wenn Sie mit dem Wert vorbei sind dann egal, es nicht zu die Außenwelt, wenn Sie den Parameter als const markieren.

Um Ihre Frage so direkt wie möglich zu beantworten, ist es nicht falsch, die andere Klasse nach Wert zu nehmen. Wenn die Objekte kleiner sind, ist es besser, den Wert zu übergeben. In Ihrem Fall ist der Größenunterschied 0 auf einer typischen 64-Bit-Plattform (2 * 4 Bytes pro Int im Vergleich zu einem 8-Byte-Zeiger). So Ihre „4 Bytes auf dem Stack“ tatsächlich nicht existiert, es ist die gleiche Größe

Ich würde ein optimierenden Compiler vorhersagen Ihren Code neu zu schreiben die Crate von Wert zu nehmen, auch wenn Sie es erklären, wie durch Bezugnahme nehmen. Dies würde aus Gründen der räumlichen Lokalität und des leichten Zugangs erfolgen. Wenn ein Zeiger übergeben wird, müssen Sie dem Zeiger folgen, um zu den Datenelementen zu gelangen, wodurch ein Schritt hinzugefügt wird.

Ihr Professor ist falsch, Ihnen 0 Punkte dafür zu geben, es sei denn, es wurde eine Anforderung sehr klar gemacht, dass alle Operatoren Referenzparameter nehmen müssen. Das const Crate vs Crate Problem spielt keine Rolle.

+0

Danke für die Korrektur des Tippfehlers in meiner Antwort. – SergeyA

4

Sie sollten keine 0 erhalten haben, aber Sie sollten auch keine vollständige Gutschrift erhalten haben.

friend ostream& operator<< (ostream& out, Crate c) 

Wird eine Kopie jedes Mal erstellen, wenn Sie es anrufen, was ineffizient sein kann. Um zu vermeiden, diese Kopien Sie wie

durch Verweis übergeben wollen
friend ostream& operator<< (ostream& out, Crate& c) 

Aber dies stellt ein neues Problem, dass Ihre erste Version nicht hatte, wie unter Bezugnahme auf Pass benötigen Sie einen L-Wert an die Funktion zu liefern. Sie würden es nicht in der Lage sein zu verwenden, wie

std::cout << Crate(); 

zu bekämpfen, dass wir die Crate von const & nehmen können, welche Kopien vermeiden und ermöglicht es uns, Provisorien zu binden

friend ostream& operator<< (ostream& out, const Crate& c) 
+2

Seine Klasse enthält 2 Ints. Es nach Wert zu übergeben ist überhaupt nicht ineffizient. –

+0

@BenjaminLindley Das stört mich auch. Ich habe es auf * aktualisiert * – NathanOliver

3

Studium ist in der Regel über gute Gewohnheiten und allgemeines Wissen, viel weniger von einem kleinen Beispiel, das du schreibst.

Ja, in Ihrem Fall wird die performanceorientierte Wertübernahme nichts ändern. Aber es gibt zwei Probleme damit:

  • Gewohnheit. Sie sollten sich angewöhnen zu wissen, wie Sie Ihre Argumente weitergeben. Wenn eine Änderung nicht erforderlich ist und die Daten nicht verschoben werden sollen, übergeben Sie const referenz;
  • Wie Sie es geschrieben haben, muss Ihre Klasse kopierfähig sein. Deines ist, aber es ist nicht immer der Fall.

Wie für die tatsächliche Null als eine Marke - nicht darüber schwitzen. Bedeutet nichts.

+2

Eigentlich war es wahrscheinlich nützlich. Zehn Dollar sagt, dass OP mehr gelernt hat als die meisten seiner Klassenkameraden, indem er den Code bis auf die kompilierte Ausgabe untersucht und untersucht. Zerrissen auf ihre Klasse, ja, aber langfristig vorteilhaft. – user4581301