Wenn die Rückgabe eines Zeigers, Skalar-und Referenz-in C++?
Ich bin bewegt von Java zu C++ und bin ein bisschen verwirrt von der Sprache, die Flexibilität. Ein Punkt ist, dass es gibt drei Möglichkeiten, um Objekte zu speichern: ein Zeiger, Eine Referenz und ein Skalar (das speichern des Objekts selbst, wenn ich es richtig verstanden habe).
Ich Neige dazu, verwenden Sie Referenzen, wo dies möglich ist, denn das ist, wie nah an Java wie möglich. In einigen Fällen, z.B. Getter für abgeleitete Attribute ist dies nicht möglich:
MyType &MyClass::getSomeAttribute() {
MyType t;
return t;
}
Diese nicht kompilieren, weil t
besteht nur im Rahmen des getSomeAttribute()
und wenn ich wieder ein Verweis darauf, es würde den Punkt im nirgendwo, bevor der client es benutzen kann.
Daher bin ich Links mit zwei Optionen:
- Gibt einen Zeiger
- Rückgabe eines skalaren
Rückgabe einen Zeiger würde dann so Aussehen:
MyType *MyClass::getSomeAttribute() {
MyType *t = new MyType;
return t;
}
Dieser funktionieren würde, aber der Kunde hätte dies zu prüfen Zeiger für NULL
um wirklich sicher sein, etwas, das nicht notwendig mit Referenzen. Ein weiteres problem ist, dass der Anrufer sicherstellen, dass t
freigegeben ist, würde ich eher nicht deal mit, dass, wenn ich es vermeiden kann.
Die alternative wäre die Rückkehr auf das Objekt selbst (Skalar):
MyType MyClass::getSomeAttribute() {
MyType t;
return t;
}
Dass ist ziemlich einfach und nur was soll ich in diesem Fall: Es fühlt sich an wie eine Referenz, und es kann nicht null sein. Wenn das Objekt außerhalb des Bereichs befindet, in der client-code wird gelöscht. Ziemlich praktisch. Ich habe jedoch selten das jemand tut, gibt es einen Grund für das? Gibt es irgendeine Art von performance-problem, wenn ich wieder ein Skalar statt ein Zeiger oder ein Verweis?
Was ist der häufigste/eleganter Ansatz, dieses problem zu behandeln?
- "Ich bin bewegt von Java zu C++" bedeutet nichts. Ist Java nicht C++. Java wird nie C++. Denken Sie über Java beim Programmieren mit C++ ist nicht zu helfen, Sie verstehen, C++ oder Ihnen helfen, gute Entscheidungen zu treffen. Jede Sprache wird Ihnen nicht helfen, das Programm gute C++ - Ausnahme C++, also vergessen Sie Sie wissen, alle anderen Sprachen, weil Sie nicht C++. Sie müssen lernen, C++, wenn Sie möchten, Programmieren in C++, nicht versuchen sich zu ändern eine bereits vorhandene Sprache in C++, denn das wird nicht funktionieren, da nur C++ ist C++. Kann ich empfehlen ein gutes Buch?
- Eine Referenz ist nicht in der Nähe, was Java tut. Die nächste Sprache, die nur konstruieren zu Java wäre die Rückgabe eines Zeigers an. Aber das bedeutet nicht das Konto für die Verwaltung des Speichers. So die nächsten C++ - Konstrukt von Java würde die Rückkehr ein shared pointer. std::tr1::shared_ptr<T> (oder std::shared_ptr<T> oder boost::shared_ptr (je nachdem, welche version Sie verwenden)). Sie können neue und vergessen, zu Ihrem Herzen Inhalt und in der Regel wird das Objekt der garbage Collection freigegeben wird, richtig. Aber C++ ist nicht Java. Sie müssen lernen, wie man Werte richtig. Bitte bringen Sie Java-Konzepte von C++, die Sprachen sind nur anders.
- Ok also C++ ist nicht Java, aber ignorieren Sprache Besonderheiten. Ideen, ausgedrückt in Java übersetzt werden können, um C++. Ich habe oft das Programm in einer Anzahl von Sprachen, die oft die syntax unterscheidet sich, nicht aber die Semantik.
- ist nicht 'unbedingt', und in diesem Fall es ist nicht nur Semantik. "Ideen" ist so ein allgemeiner Begriff deine Argumentation ist weder widerlegbar bzw. sinnvoll ist. C++ und Java sind unterschiedliche Sprachen, und Sie tun die Dinge auf unterschiedliche Weise. Die "Ideen", die übereinstimmen, sind Grundlagen wie z.B. dem ausführen von Anweisungen, und sagen Sie nichts über design-Entscheidungen.
- Das ist ein Missverständnis.
- Mit Hilfe der "Vergleichenden Analyse" ist eine sehr menschliche und sehr Häufig, was zu tun ist. Ich habe festgestellt, dass es ein großartiges Werkzeug, um zu helfen, lehren die Menschen. Ich werde nie verstehen, die "Folgen der Herde, geschlossen-mind" - Ansatz.
- Sie haben nicht zu prüfen, die Rückkehr der
new
für NULL odernullptr
.new
garantiert eine exception werfen, auf allocation failure.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Rückkehr von Wert. Der compiler kann optimieren der Weg der Kopie, so dass das Endergebnis ist, was Sie wollen. Ein Objekt wird erstellt und an den Aufrufer zurückgegeben.
Ich denke, der Grund, warum Sie nur selten sehen die Menschen tun dies, weil Sie sehen das falsch, C++ - code. 😉
Die meisten Menschen kommen aus Java, fühlen sich unwohl, etwas wie das zu tun, so nennen Sie
new
alle über dem Platz. Und dann bekommen Sie Speicher-Lecks alle über den Ort, überprüfung auf NULL-und alle die andere Probleme verursachen können. 🙂Könnte es auch sein, darauf hinzuweisen, dass C++ - Referenzen, haben sehr wenig gemein mit Java-Referenzen.
Eine Referenz in Java ist viel mehr ähnlich wie ein Zeiger (es kann sein, umgesetzt oder auf NULL gesetzt).
In der Tat ist die einzige wirkliche Unterschiede sind, dass ein Zeiger kann auf eine Müll-Wert als auch (wenn es nicht initialisiert ist, oder es verweist auf ein Objekt, dass mehr Umfang), und dass Sie tun können, pointer-Arithmetik auf einen Zeiger in ein array.
Ein C++ - Referenzen ist ein alias für ein Objekt. Eine Java-Referenz verhält sich nicht so.
A a = B->GetA()
woB::GetA
erklärt wirdconst A& B::GetA()
oder auch ohne const, wird zu einer Kopie.Ganz einfach, vermeiden Sie die Verwendung von Pointern und dynamische Zuweisung von
new
wo immer möglich. Verwenden Sie die Werte, Referenzen und automatisch zugewiesenen Objekte statt. Natürlich kann man nicht immer vermeiden, die dynamische Zuweisung, aber es sollte ein letzter Ausweg, nicht die erste.Rückkehr mit dem Wert vorstellen können Leistungseinbußen, weil dies bedeutet, dass das Objekt kopiert werden muss. Wenn es ein großes Objekt, wie eine Liste, die operation kann sehr teuer sein.
Aber moderne Compiler sind sehr gut über die Herstellung dieses nicht passieren. Die C++ standards, die explizit besagt, dass der compiler darf elide Kopien unter bestimmten Umständen. Die Besondere Instanz, die im Beispiel-code, den Sie gab, wird als "return value optimization'.
Persönlich, ich komme (in der Regel const -) Referenz, wenn ich fahre eine member-variable, und wieder einige Sortieren von smart-pointer-Objekt irgendeiner Art (oft
::std::auto_ptr
), wenn ich dynamisch reservieren etwas. Ansonsten habe ich die Rückkehr von Wert.Habe ich auch sehr Häufig
const
Referenz-Parameter, und dies ist sehr Häufig in C++. Dies ist eine Möglichkeit, einen parameter übergeben und sagen: "die Funktion ist nicht erlaubt zu berühren". Im Grunde eine nur-lese-parameter. Es sollte nur verwendet werden, für Objekte, die komplexer sind als eine einzelne ganze Zahl oder ein Zeiger, obwohl.Ich denke, eine große Umstellung von Java ist, dass
const
ist wichtig und sehr Häufig verwendet. Lernen, Sie zu verstehen und machen es zu Ihrem Freund.Ich denke auch, dass Neil ' s Antwort die richtige in die besagt, dass Vermeidung die dynamische Zuordnung, Wann immer möglich, ist eine gute Idee. Sollten Sie sich nicht verziehen das design zu viel zu machen, dass passieren, aber Sie sollten auf jeden Fall bevorzugen design-Entscheidungen, in denen es nicht passieren.
const
haben, eine strengere definition, weil der Objekt-Status im Arbeitsspeicher, die eigentlich nicht beschreibbar ist.mutable
.Rückkehr von Wert ist eine gemeinsame Sache heute in C++. Allerdings, wenn Sie übergeben ein Objekt, das Sie übergeben nach Verweis.
Beispiel
Oben ist ein einfaches Beispiel für die übergabe eines Objekts als Referenz. In der Realität, Sie würden eine Methode namens isTraderAllowed für die Klasse equity, aber ich zeigte Ihnen einen echten nutzen von der übergabe by reference.
Einen Punkt in Bezug auf die übergabe per Wert oder Referenz:
Angesichts Optimierungen, unter der Annahme einer Funktion ist inline, wenn der parameter deklariert ist als "const DataType objectName", der Datentyp kann alles sein, sogar primitiven, kein kopieren von Objekten beteiligt sein wird; und wenn seine parameter deklariert wird als "const DataType & objectName" oder "DataType & objectName", der wiederum Datentyp kann alles sein, sogar primitiven, keine Adresse oder Zeiger beteiligt sein werden. In den beiden vorigen Fällen, die input-Argumente sind, die direkt in Assembler-code.
Einen Punkt bezüglich der Verweise aus:
Eine Referenz ist nicht immer ein Zeiger, wie etwa, wenn Sie folgenden code im Hauptteil einer Funktion, die Referenz ist kein Zeiger:
Einen Punkt bezüglich der Rückkehr von Wert:
einige Leute haben erwähnt, mit guten Compiler mit der Möglichkeit von Optimierungen bei der Rückkehr mit dem Wert von jeder Art wird nicht dazu führen, eine zusätzliche Kopie.
Einen Punkt in Bezug auf Rückgabe durch Referenz:
Im Falle von inline Funktionen und Optimierungen, die Rückgabe durch Referenz wird nicht mit der Adresse der Einnahme oder Zeiger.