Warum ist es OK, um zurück-vector-aus-Funktion?
Bitte betrachten Sie diesen code. Ich habe gesehen, diese Art von code mehrmals. words
einen lokalen Vektor. Wie ist es möglich, zu ihm zurückzukehren, der von einer Funktion? Können wir garantieren, es wird nicht sterben?
std::vector<std::string> read_file(const std::string& path)
{
std::ifstream file("E:\\names.txt");
if (!file.is_open())
{
std::cerr << "Unable to open file" << "\n";
std::exit(-1);
}
std::vector<string> words;//this vector will be returned
std::string token;
while (std::getline(file, token, ','))
{
words.push_back(token);
}
return words;
}
- Es kopiert wird, wenn Sie zurückkehren.
- Garantiert niemand.. Es sterben wird, aber nachdem es kopiert.
- Sie haben nur ein problem, wenn die Funktion liefert eine Referenz :
std::vector<std::string>&
- Nein, es wird verschoben werden.
- Nur garantiert in C++11?
- Ja. C++11 ist der aktuelle standard, also C++11 wird C++.
- Anscheinend sollten Sie auch vermeiden, Rückkehr Vektoren(und anderen Containern) in der öffentlichkeit .dll ' s, es sei denn, Sie können sicherstellen, dass die Laufzeit ist die gleiche. Vor allem für msvc, nicht sicher, ob gcc hat das gleiche problem.
- Aufgrund von Problemen mit den zugreifen? Ich vermute, dass verschiedene Versionen von der MSVC-runtime-Bibliotheken können einige Behälter Mitglieder in unterschiedlicher Reihenfolge, so dass selbst wenn die Container haben die richtige Mitglieder wie pro die standard-offsets von Anfang an das Objekt, um Zugriff auf die Mitglieder können falsch sein, wenn ein Programm zusammengestellt für eine bestimmte Laufzeit mit einem anderen? (Obwohl ich bin mir ziemlich sicher, dass die meisten kompilierte Programme dynamisch gegen die MSVC-Bibliotheken erforderlich, den spezifischen DLLs waren Sie verbunden mit sowieso, aber das gleiche Prinzip gilt für die zwei statisch gelinkte Programme/DLLs.)
- möglich, Duplikat der In C++ ist es immer noch schlechte Praxis, um wieder eine Vektor-Funktion?
- Ja, offenbar seine zu tun, mit der Möglichkeit der einzelnen layouts. Ich denke, dass Sie funktionieren, geladen werden, Seite an Seite, nur nicht über die dll-Grenze.
- nrvo nicht auch hier passieren?
Du musst angemeldet sein, um einen Kommentar abzugeben.
So lange es keine Referenz zurückgegeben, es ist völlig in Ordnung, dies zu tun.
words
verschoben werden, um die Variablen erhalten das Ergebnis.Den lokalen variable geht out of scope. danach wurde es verschoben (oder kopiert).
Vor C++11:
Die Funktion wird nicht zurückkehren die lokale variable, sondern eine Kopie davon. Dein compiler kann jedoch die Durchführung einer Optimierung, wo keine aktuelle Aktion Kopie wird gemacht.
Sehen diese Frage & Antwort für weitere details
C++11:
Die Funktion wird verschoben, der Wert, siehe diese Antwort für weitere details
Ich denke, du beziehst das problem in C (und C++), dass die Rückgabe eines Arrays aus einer Funktion nicht erlaubt (oder zumindest nicht funktionieren wie erwartet) - dies ist, weil das array zurückgeben wird (wenn Sie es schreiben in der einfachen form) gibt einen Zeiger auf die eigentlichen array auf dem stack, die dann umgehend entfernt, wenn die Funktion zurückgibt.
Aber in diesem Fall, es funktioniert, weil die
std::vector
ist eine Klasse, und die Klassen, wie Strukturen, können (und werden) kopiert werden, um den Kontext der Aufrufer. [Tatsächlich, die meisten Compiler optimieren, aus dieser besonderen Art der Kopie mithilfe so genannter "Return-Wert-Optimierung", die speziell eingeführt, um zu vermeiden das kopieren großer Objekte, wenn Sie von einer Funktion zurückgegeben, aber das ist eine Optimierung, und aus Programmierer-Perspektive, er wird sich Verhalten, als ob die Abtretung Konstruktor aufgerufen wurde für das Objekt]Solange Sie nicht wieder einen Zeiger oder eine Referenz auf etwas, das innerhalb der Funktion zurückgeben, Sie sind in Ordnung.
Gut verstehen, das Verhalten, können Sie diesen code ausführen :
Die Ausgabe ist folgende :
Ich nicht einverstanden und NICHT zu EMPFEHLEN return Vektor:
Dies ist viel schneller:
Getestet habe ich auf VS2017 mit folgenden Ergebnissen im release-Modus:
8.01 MOPs durch Verweis
5.09 MOPs Rückkehr Vektor
Im debug-Modus sind die Dinge viel schlimmer:
0.053 MOPS durch Verweis
0.034 MOPs-durch Rücksendung Vektor
Dies ist tatsächlich ein Fehler des Designs, sollten Sie sich nicht mit einem Rückgabewert für alles, was nicht eine primitive für alles, was nicht relativ trivial. Die ideale Lösung sollte umgesetzt werden durch eine return-parameter die Entscheidung mit einem Verweis/ptr und die ordnungsgemäße Verwendung der ein "const\'y\'ness" als Deskriptor.
Auf der Spitze dieses, Sie sollten wissen, dass das label auf ein array in C und C++ ist im Grunde ein Zeiger und Ihre Abonnements wirksam sind, eine Aufrechnung oder ein Plus-symbol.
So das label, oder ptr array_ptr === array label somit wieder foo[offset] ist wirklich sagen return-element im Speicher ptr Lage foo + offset vom Typ Rückgabetyp.