2017-02-08 6 views
2

In der kleinen Probe unter:Was passiert mit dem Rückgabewert, wenn ich ihn nirgendwo aufbewahre?

#include<iostream> 
using namespace std; 

int z(){ 
    return 5 + 10; // returns 15 
} 

int main(){ 
    z(); // what happens to this return? 
    cout << "Did not fail"; 
    return 0; 
} 

Was ist mit den 15 passiert? Ich habe versucht, es im Debugger auszuführen, aber ich kann es nirgends finden. Ich nehme an, dass, weil es zu nichts zugewiesen wurde, es einfach verschwunden ist, aber ich fühle mich wie falsch.

Ich fragte meine TA heute und er sagte mir, es ist auf dem Aufruf-Stack gespeichert, aber wenn ich es im Debugger sah, sehe ich, dass es nicht ist.

+4

Es verschwindet. Wie genau dies geschieht, hängt von den Aufrufkonventionen ab. Sagen wir, einige von ihnen übergeben den Rückgabewert in einem der Register (und dann können Sie es dort sehen), einige übergeben sie über Stapel (und der Aufrufer lässt nur diesen Wert fallen). Außerdem kann der Optimizer auch hier spielen: Er kann die Funktion inline und die nutzlose Berechnung ablegen. Vielleicht möchten Sie sich den Assembler-Code anschauen, um zu sehen, was genau passiert. – yeputons

+0

@yeputons Danke! Also meine Annahme war richtig. Ich denke, ich habe jetzt noch mehr Nachforschungen anzustellen. – Callat

Antwort

9

Der C++ - Standard schreibt die "als-ob" -Regel vor. Diese Regel bedeutet, dass ein C++ - Compiler alles für ein Programm tun kann, solange alle Nebeneffekte (Eingaben und Ausgaben, die für den Rest des Systems sichtbar sind, wie das Schreiben in eine Datei oder Anzeigen von Inhalten auf dem Bildschirm) respektiert werden. Geht man zurück zu meinem cheeky philosophical comment, bedeutet dies, dass in C++, wenn ein Baum in den Wald fällt und niemand dort zu hören ist, es nicht hat, einen Ton zu machen (aber es kann).

Im Fall Ihres Programms, auf hoher Ebene, da Ihre Funktion nichts tut, kann der Compiler einen Aufruf erstellen oder auch nicht, oder könnte es sogar aus der kompilierten Binärdatei entfernen. Wenn es den Wert enthält und aufruft, wird der Rückgabewert an den Rückgabebereich gesendet, den die binäre Schnittstelle der Plattform für Ihre Plattform angibt. Auf fast jedem x86_64-System wird dies das rax-Register für einen Integer-Rückgabewert sein. Der Rückgabewert ist dort, wird aber nie gelesen und irgendwann überschrieben.

Wenn es ein nicht-triviales Objekt anstelle von int wäre, würde sein Destruktor sofort aufgerufen werden.

+3

Als Referenz, alle 'icc ',' clang' und 'gcc' noch _include_' z() 'in der [kompilierten binären] (https://godbolt.org/g/ZPa39l), aber keiner von ihnen tatsächlich nennen. Vielleicht liegt das daran, dass Compiler Symbole, die nicht notwendigerweise lokal zur Kompilierungseinheit sind, nicht generell ausschließen können (ich nehme an, Sie könnten sie irgendwie verknüpfen oder dynamisch laden). Wenn Sie 'z()' als 'static' deklarieren, [alle oben genannten lassen es vollständig weg] (https://godbolt.org/g/3Fa2MH). Wenn der Compiler den Textkörper von 'z() nicht sehen kann, wird die Funktion noch aufgerufen, aber der Rückgabewert' eax' [wird ignoriert] (https://godbolt.org/g/w72NWM). – BeeOnRope

4

Allgemein: Wenn eine Funktion einen Wert ungleich void zurückgibt und der Wert nirgendwo gespeichert wird, wird der Wert zerstört.

Speziell: natürliche Datentypen, wie int s und double s, oder Zeiger, haben keinen expliziten Destruktor, also passiert nichts wirklich. Der zurückgegebene Wert wird einfach ignoriert.

Wenn eine Funktion eine Klasseninstanz zurückgibt, wird die Klasseninstanz zerstört, was zu einem Aufruf des definierten Destruktors der Klasse oder eines Standarddestruktors führt.

Verwandte Themen