HOWTO · C++
Fehler Control Reaches End of Non-Void Function in C++ beheben
Erfahren Sie, warum eine C++-Funktion, die nicht void ist, ihre schließende Klammer erreichen kann, wie Sie alle Rückgabewege abdecken und wann ein Ausweichwert oder eine Compilerwarnung hilft.
Auf dieser Seite
Eine C++-Funktion, deren Rückgabetyp nicht void ist, muss auf jedem erreichbaren Pfad einen Wert liefern. Die Ausnahme ist main: Wird das Ende dieser Funktion erreicht, wird implizit 0 zurückgegeben. Erreicht ein erreichbarer Pfad in einer anderen Funktion mit Rückgabewert die schließende Klammer, ohne einen Wert mit return zurückzugeben, ist das Verhalten undefiniert. Je nach Code und Warnungseinstellungen kann der Compiler außerdem auf diesen Pfad hinweisen. Verfolgen Sie zur Behebung jeden Zweig und stimmen Sie den Rückgabewert auf den Zweck der Funktion ab.
Den Fehler verstehen
Eine Funktion mit Rückgabewert verspricht einen Wert des deklarierten Typs. Die häufig als „control reaches end of non-void function“ bezeichnete Compilermeldung weist auf einen Pfad hin, der die schließende Klammer erreichen kann, ohne diesen Wert zurückzugeben. Das Problem besteht nicht einfach darin, dass am Ende eine Anweisung fehlt: Eine vorherige Bedingung kann dazu führen, dass für manche Eingaben kein Ergebnis geliefert wird. Zum Beispiel gibt int add(int a, int b) { if (a > b) return a + b; } keinen Wert zurück, wenn a <= b gilt. Wird auf diese Weise das Ende einer Funktion mit Rückgabewert erreicht, die nicht main ist, ist das Verhalten undefiniert; ein bestimmter Absturz oder ein bestimmtes Ergebnis ist nicht garantiert.
Führen Sie dieses Beispiel aus:
#include <iostream>
int add(int a, int b) {
return a + b;
}
int main() {
std::cout << add(5, 3) << '\n';
}
8
Das Programm gibt für diese Eingabe die Summe zurück. Die obige Inline-Version zeigt die Ursache der Diagnose; die ausführbare Version behebt sie, indem sie für jede Eingabe einen Wert zurückgibt.
Sicherstellen, dass jeder Pfad einen Wert zurückgibt
Verfolgen Sie die Bedingungen und legen Sie fest, was jeder Fall bedeuten soll. Bei einer Addition sollte die Summe unabhängig von der Reihenfolge der Operanden zurückgegeben werden. Wenn die Bedingung für weitere Aufgaben erforderlich ist, kann ein abschließendes return den verbleibenden Pfad abdecken. Wenn beide Zweige dasselbe tun, entfernen Sie die Bedingung:
#include <iostream>
int add(int a, int b) {
if (a > b) {
return a + b;
}
return a + b;
}
int main() {
std::cout << add(3, 5) << '\n';
}
Eine vollständige Verzweigung ist sinnvoll, wenn die Fälle unterschiedliche Bedeutungen haben. Dieses Beispiel gibt den größeren Operanden zurück und deckt beide Pfade ab:
#include <iostream>
int larger(int a, int b) {
if (a > b) {
return a;
} else {
return b;
}
}
int main() {
std::cout << larger(5, 3) << '\n';
}
Prüfen Sie auch verschachtelte Bedingungen und switch-Anweisungen: Jeder Pfad durch eine Funktion mit Rückgabewert muss einen Wert zurückgeben oder anderweitig verhindern, dass die schließende Klammer erreicht wird.
Standard-Rückgabewerte verwenden
Ein abschließendes return kann als Rückfallwert für Fälle dienen, die keine vorherige Bedingung erfüllen. Verwenden Sie einen solchen Wert nur, wenn er dem Vertrag der Funktion entspricht. Diese Suchfunktion gibt beispielsweise für einen gefundenen Namen eine bekannte Punktzahl und bei einem fehlenden Namen 0 zurück. Dieser Rückfallwert ist nur dann passend, wenn die Anwendung eine fehlende Punktzahl als null definiert.
#include <iostream>
#include <string>
int scoreFor(const std::string& name) {
if (name == "Ada") {
return 10;
}
return 0;
}
int main() {
std::cout << scoreFor("Ada") << '\n';
std::cout << scoreFor("Lin") << '\n';
}
Wenn das Fehlen eines Werts einen eigenen Fall darstellt, kann die Rückgabe von 0 diesen Unterschied verschleiern. Wählen Sie einen Rückgabetyp und ein Ergebnis, die den tatsächlichen Vertrag ausdrücken, etwa einen optionalen Wert oder einen ausdrücklichen Status. Fügen Sie keinen beliebigen Rückfallwert nur hinzu, um eine Diagnose zum Verschwinden zu bringen.
Mit Compiler-Warnungen Fehler suchen
Aktivieren Sie beim Kompilieren Warnungen, damit der Compiler Ihnen einen zu untersuchenden Pfad anzeigen kann. Der Befehl g++ -Wall -Wextra -Wreturn-type your_code.cpp -o your_program weist GCC beispielsweise an, verschiedene Warnungen auszugeben, darunter gegebenenfalls auch Hinweise auf problematische Rückgabepfade. Verfügbarkeit und Wortlaut von Warnungen hängen vom Compiler, seiner Version, den Optionen und dem Code ab. Eine Warnung ist ein Hinweis darauf, den Kontrollfluss nachzuverfolgen, und kein Beleg dafür, dass jeder Compiler den Code gleich behandelt.
Untersuchen Sie jeden Zweig, auch verschachtelte if-Anweisungen und alle Fälle einer switch-Anweisung. Entscheiden Sie dann, was die Funktion für jede Eingabe tun soll, und geben Sie einen Wert zurück, der dieses Verhalten erfüllt. Lassen Sie Warnungen während der Entwicklung aktiviert, damit ähnliche Pfade leichter auffallen.
Fazit
Kann eine C++-Funktion mit Rückgabewert ihre schließende Klammer ohne einen Wert erreichen, verfolgen Sie den betreffenden Pfad und korrigieren Sie die Logik der Funktion. Decken Sie jeden Fall mit einem Rückgabewert ab, der zum Zweck der Funktion passt. Verwenden Sie einen Rückfallwert nur, wenn er eine festgelegte Bedeutung hat, und betrachten Sie Compiler-Warnungen als Hilfe beim Auffinden prüfenswerter Pfade.
Häufig gestellte Fragen
Was verursacht die Diagnose „control reaches end of non-void function“?
Ein erreichbarer Pfad in einer Funktion, die einen Wert zurückgibt, erreicht die schließende Klammer, ohne einen Wert zurückzugeben. Compiler können auf diesen Fall hinweisen; Diagnose und Build-Verhalten hängen jedoch vom Compiler und seinen Optionen ab.
Muss jeder if-Zweig ein return enthalten?
Nein. Ein return nach der Bedingung kann den verbleibenden Pfad abdecken. Entscheidend ist, dass kein erreichbarer Pfad ohne Wert am Funktionsende ankommt.
Sollte ich return 0; hinzufügen, damit die Warnung verschwindet?
Nur wenn null gemäß dem Vertrag der Funktion ein gültiges Ergebnis ist. Andernfalls sollten Sie ein Ergebnis oder einen Rückgabetyp wählen, der den fehlenden Fall zutreffend ausdrückt.
Kann eine Compiler-Warnung den fehlenden Pfad finden?
Sie kann auf eine Funktion hinweisen, bei der der Kontrollfluss möglicherweise bis zum Ende durchläuft. Untersuchen Sie damit den Kontrollfluss; Wortlaut und Verhalten der Warnung unterscheiden sich je nach Compiler und Einstellungen.