Also, ich war immer ein wenig unscharf auf C ++ - Zeigern vs. ... wie auch immer der andere heißt. Wie,
%Vor%gegen
%Vor%Ich weiß, dass Zeiger wahrscheinlich in den zweiten eingebunden sind, aber im Grunde ist es ein Nicht-Zeiger. (Wie heißt es eigentlich?)
Außerdem glaube ich, dass Sie für die erste
anrufen müssen %Vor%irgendwann, wenn Sie damit fertig sind, oder? Und über den anderen musst du dir keine Sorgen machen. Ich habe gelesen, dass der erste auf dem Heap zugeordnet ist, aber der zweite auf dem Stapel zugeordnet ist und verschwindet, wenn die Methode zurückkehrt.
Aber was ist, wenn Sie etwas (nicht ein primitives) von einer Funktion zurückgeben?
Ein gutes Beispiel finden Sie in Soll ich std :: strings zurückgeben? :
%Vor%Nach dem, was ich vorher geschrieben habe, wird die Zeichenfolge auf dem Stapel zugewiesen und sollte freigegeben werden, wenn die Funktion zurückkehrt, richtig? Aber niemand hat etwas darüber gesagt, also nehme ich an, es funktioniert gut. Warum?
Was ist der Unterschied zwischen
? %Vor%und
%Vor%?
Wenn beide Arbeiten angenommen werden, was sind dann die Vor- und Nachteile der beiden?
Wenn Sie mit Zeiger zurückkehren, müssen Sie ein dynamisch zugewiesenes Objekt wie angegeben zurückgeben (d. h., ein Zeiger auf ein Stapelobjekt zurückgibt, führt zu einem nicht definierten Verhalten, wenn es später dereferenziert wird). Dies schafft ein Potential für Speicherlecks, weil, wie Sie bemerkt haben, dieses Objekt explizit gelöscht werden muss.
Wenn Sie andererseits den Wert zurückgeben (d. h. das zweite Snippet), wird das Objekt, das Sie von dem zurückgegebenen Stapelobjekt zurückgeben, in das Objekt kopiert, das den Rückgabewert empfängt:
%Vor%Compiler können dies optimieren, um ein Kopieren durch Rückgabewertoptimierung zu vermeiden.
Ich denke, du wolltest nicht wirklich Object notpointer();
schreiben, da dies eine Funktion mit dem Namen notpointer
deklariert, die ein Object
zurückgibt. Wenn Sie Object notpointer;
gemeint haben, handelt es sich bei den betreffenden Entitäten um Werte . Werte werden tatsächlich auf dem Stapel oder, wenn es sich zufällig um Elemente von Objekten handelt, in das Objekt eingebettet.
Beim Zurücksenden wird die zurückgegebene Entität kopiert oder an den Ort verschoben, an dem der tatsächliche Rückgabewert erwartet wird. Sobald der Rückgabewert konstruiert ist, geht das lokale Objekt, d. H. Diejenigen auf dem Stapel, außer Reichweite und werden zerstört. Da die lokalen Objekte sowieso verschwinden, kann der Compiler die Kopie freigeben und das Objekt sofort am richtigen Ort konstruieren, selbst wenn der Kopierkonstruktor und / oder der Destruktor Nebenwirkungen haben.
Der Unterschied zwischen Ihren beiden Return-Anweisungen ist
Wenn Sie new std::string("pointer")
verwenden, erhalten Sie ein Objekt, das auf dem Heap zugeordnet ist, und Sie geben einen Zeiger auf das Objekt zurück. Es ist sehr einfach, diesen Zeiger zu verlieren, und es wäre besser, ihn sofort in ein geeignetes Objekt zu stellen, z. B. std::unique_ptr<std::string>
:
Auf diese Weise wird der Zeiger nicht durchgesickert. Natürlich würden Sie auch den Rückgabetyp ändern, um ein std::unique_ptr<std::string>
anstatt ein std::string*
zu sein. Beachten Sie, dass die Heapzuweisungen im Allgemeinen ziemlich teuer sind.
std::string("value")
verwenden, geben Sie nur eine lokale Variable zurück. Es besteht eine gute Chance, dass die Kopie entfernt wird und der Rückgabewert sofort an dem Ort erstellt wird, an den er gehen soll. Es ist nicht nötig, sich um Ressourcen zu kümmern, da alle beteiligten Objekte automatisch zerstört werden. Es gibt keine explizite Heap-Zuweisung und die Stack-Zuweisung ist sehr schnell. Natürlich muss in dem gegebenen Beispiel die std::string
in beiden Fällen ihre interne Repräsentation zuweisen. Wenn der Zeiger zurückgegeben wird, ist sichergestellt, dass es keine zusätzliche interne Zuweisung gibt. Wenn andererseits ein std::string
-Wert zurückgegeben wird und tatsächlich kopiert werden muss, muss möglicherweise der interne Speicher für die Kopie zugewiesen werden. Das heißt, wenn große Objekte zurückgegeben werden, die möglicherweise viele Speicherzuweisungen erfordern, besteht bei der Methode, die einen Wert zurückgibt, das Risiko, dass sie kopiert werden muss. Mit dem aktuellen C ++ werden die Objekte jedoch im schlimmsten Fall bewegt, d. H. Es gibt nicht so viele Bedenken beim Kopieren der Objekte als in C ++ 03.