Die Rückgabe von Exemplaren in C++ [] (Die Rückgabe von Exemplaren in C++), lesson, page 722662
https://www.purl.org/stefan_ram/pub/exemplarrueckgabe_c++ (permalink) is the canonical URI of this page.
Stefan Ram
C++-Kurs

Rückgabe von Exemplaren in C++ 

Wie schon im Grundkurs an Hand von »::std::string« gezeigt, kann der Rückgabetyp einer Funktion auch ein benutzerdefinierter Typ sein. Im allgemeinen muß der return-Ausdruck dann dazu passen.

Wie schon bei der Argumentaufgabe, so erfolgt auch hier die Festlegung eines Wertes mit »return« erfolgt wie bei einer Kopierinitialisierung (copy-initialization ). Eine eventuell nötig Typwandlung darf nicht explizit sein.

Syntax

return [<expr-or-braced-init-list>];
main.c

#include <initializer_list>
#include <ostream>
#include <iostream>
#include <string>

using namespace ::std::literals;

::std::string f(){ return "abc"s; }
::std::string g(){ return "abc"; }
::std::string h(){ return { 65, 66 }; }

int main()
{ ::std::cout << f() << '\n'; /* schreibt "abc" */
::std::cout << g() << '\n'; /* schreibt "abc" */
::std::cout << h() << '\n'; /* schreibt "AB" */ }

Durch gewisse Tricks, kann eine moderne C++-Implementation es in der Regel vermeiden, daß größere Objekte bei der Rückgabe zeitaufwendig kopiert werden müssen. Deswegen ist heute nicht mehr verpönt, auch größere Objekt direkt zurückzugeben.

Rückgabe von Referenzen

Die Lebenszeit von Parametern und lokalen Variablen in Funktionsinkarnationen endet (mit einer Ausnahme) mit dem Ende der Lebenszeit der Funktionsinkarnation. Daher ist es nicht sinnvoll, Referenzen auf solche Objekte aus einer Funktion zurückzugeben. Denn wenn der Aufrufer die erhaltene Referenz verwenden kann, ist das Objekt schon erloschen.

Das folgende Programm deklariert die Rückgabe einer Referenz  auf ein Objekt vom Typ "double". Dadurch bewirkt die Anweisung "return result;" nicht die Rückgabe des Wertes  (Rechtswertes) des Objektes "result" sondern die Rückgabe einer Referenz auf das Objekt "result".

referenzreturn.cpp
#include <iostream> 
#include <ostream> 
#include <initializer_list>
double & kelvin( double const celsius ) 
{ double result( celsius + 273.15 );  
return result; }
int main(){ std::cout << kelvin( 22.0 )<< '\n'; }

Die Inkarnation einer Funktion ist ein Behälter für alle lokalen Definitionen der Funktion. Daher endet die Lebenszeit der lokalen Objekte mit der Inkarnation der Funktion. So endet auch die Lebenszeit der Objektes "result" mit dem Ende der Funktionsinkarnation der Funktion "kelvin". Die zurückgegebene Referenz ist für den Klienten der Funktion also bedeutungslos und darf nicht verwendet werden, weil sie eine Referenz auf ein nicht mehr existentes Objekt darstellt.

Rückgabe einer Referenz auf nicht mehr existentes Objekt
 |Zeit    main 
| .-------------------. 
| | | 
| | | 
| | << kelvin( 22.0 ) | double & kelvin 
| | | .--------------------. 
| | | | ( double const | 
| | '-------> celsius ) | 
| | | { double | Anfang der 
| | | result ( | Lebenszeit von 
| | | celsius + 273.15 );| "result" 
| | | | 
| | Referenz auf das | return result;--. | 
| | Objekt "result" | } | | Ende der 
| | .-----------------------------' | Lebenszeit von 
| | | '--------------------' "result" 
| | | | 
| | V | 
| | << kelvin( 22.0 ) | 
| | | 
| | | 
| | | Fehler: Bezug auf nicht mehr 
| | | existentes Objekt. 
V '-------------------'

In bestimmten Fällen kann die Rückgabe einer Objektreferenz sinnvoll sein (nämlich dann, wenn das Objekt noch weiterexistiert). Man muß aber grundsätzlich immer sicherstellen, daß nur Referenzen auf existierende Objekte verwendet werden.

Ein solcher Fall kann gegeben sein, wenn eine Funktion ein vorübergehendes Objekt zurückgibt, das an einen Referenzparameter gebunden ist. Dessen Existenz ist während der Auswertung des den Funktionsaufrufs enthaltenden Vollausdrucks garantiert. Von dieser Garantie sollte aber nur mit Vorsicht Gebrauch gemacht werden, weil anscheinend harmlose Änderungen an solch einem Vollausdruck dann zu Fehlern führen können.

Referenzen auf lokale Variablen in Rückgaben

Man muß daran denken, daß die Existenz einer lokalen Variablen mit der Existenz der Inkarnation der sie enthaltenden Funktion endet. Daher wäre die Rückgabe einer Referenz auf eine lokale Variablen in der Regel eine Rückgabe einer Referenz auf ein nicht mehr existentes Objekt. Solch eine Rückgabe sollte daher vermieden werden.

Rückgabe von Referenzen in sinnvoller Weise

»::std::cout« kann nicht kopiert werden, und die Rückgabe erlaubt bequeme Verwendungen.

main.cpp
#include <iostream>
#include <ostream>
#include <string>
#include <memory>
using namespace ::std::literals;

::std::ostream & put_example( ::std::ostream & stream )
{ return stream << "example"s; }

int main(){ put_example( ::std::cout ).put( '\n' ); }
::std::cout
example

About this page, Impressum  |   Form for messages to the publisher regarding this page  |   "ram@zedat.fu-berlin.de" (without the quotation marks) is the email-address of Stefan Ram.   |   A link to the start page of Stefan Ram appears at the top of this page behind the text "Stefan Ram".)  |   Copyright 1998-2014 Stefan Ram, Berlin. All rights reserved. This page is a publication by Stefan Ram. relevant keywords describing this page: Stefan Ram Berlin slrprd slrprd stefanramberlin spellched stefanram722662 stefan_ram:722662 Die Rückgabe von Exemplaren in C++ Stefan Ram, Berlin, and, or, near, uni, online, slrprd, slrprdqxx, slrprddoc, slrprd722662, slrprddef722662, PbclevtugFgrsnaEnz Erklärung, Beschreibung, Info, Information, Hinweis,

Copyright 1998-2014 Stefan Ram, Berlin. All rights reserved. This page is a publication by Stefan Ram.
https://www.purl.org/stefan_ram/pub/exemplarrueckgabe_c++