Referenz auf lokale Variable



  • Hallo.
    Als Rückgabewert hätte ich gerne eine Referenz, da ich eine große Datenstruktur zurückgebe. Ist es dann gültig, eine in der Funktion deklariert Variable als Referenz zurückzugeben?
    Beispiel:

    struct Daten
    {
    ...//viel
    }
    
    Daten& BerechneDaten(const Parameter &test, const float def)
    {
      Daten tempDaten;//Die hier wird zurückgegeben
    
      //Programmtext...
      //-----||--------
    
      return tempDaten;
    }
    

    Danke.



  • Nein. Du kannst keine Referenz auf eine lokale Variable zurückgeben , da die nach dem verlassen der Funktion zerstört wird. Also entweder gibts du die komplette Struktur zurück (dann wird sie kopiert) oder du deklarierst sie als 'static'. Dann kannst du auch eine Referenz zurück geben. Die dritte Möglichkeit wäre, die Struktur mit 'new' auf dem Heap anzulegen. 🙂



  • Für mich ist das ein typischer Fall für auto_ptr



  • struct Daten
    {
    ...//viel
    }

    Daten& BerechneDaten(const Parameter &test, const float def)
    {
    Daten tempDaten;//Die hier wird zurückgegeben

    //Programmtext...
    //-----||--------

    return tempDaten;
    }

    tempDaten wird ja gelöscht sobald du aus dem funktionsscope draußen bist. eine möglichkeit wäre in der Funktion die struct auf dem heap zu erzeugen, also
    Daten* tempDaten = new Daten
    und den Pointer zurückzugeben.
    elaganter find ich bei sowas aber referenzen als parameter, also

    void BerechneDaten(const Parameter &test, const float def, Daten& daten)

    dabei gibt die funktion nicht zurück, sondern die daten werden automatisch in die übergebene daten geschrieben.

    ansonst kannst du Daten tempDaten natürlich außerhalb deiner funktion deklarieren, ist aber wohl die mit dem hammer durch die wand methode *g*



  • Für mich ist das ein typischer Fall für "output parameter":

    Daten& BerechneDaten(const Parameter &test, const float def);
    // ->
    void BerechneDaten(const Parameter &test, const float def, Daten& output);
    


  • Oder einfach ne Kopie zurückgeben ... also Daten anstelle von Daten& ...



  • (D)Evil schrieb:

    Oder einfach ne Kopie zurückgeben ... also Daten anstelle von Daten& ...

    Wenn der Compiler nur RVO kann aber kein NRVO ist Kopie zurückgeben nicht gut.
    Wenn der Compiler NRVO kann... und man aufpasst dass er es auch machen kann...



  • templäd schrieb:

    Für mich ist das ein typischer Fall für auto_ptr

    👍
    Man braucht keine extra Zeile, um die Variable zu deklarieren um sie als Output-Parameter zu übergeben, new innerhalb & delete außerhalb einer Funktion is nix und das Objekt zu kopieren ist unnötig 🙂



  • Danke erstmal.
    Es geht in erster Linie um eine Vektorklasse und Operatoren, d.h. eine zusätzliche Referenz als Eingabeparameter kommt für mich nicht in Frage.
    Naja, dann kopiere ich halt vorerst mal alles.
    Danke.



  • Warum nicht auto_ptr?

    #include <iostream>
    #include <memory>
    using namespace std;
    
    struct Daten
    {
    	int x;
    	Daten()
    	{
    		cout << "Hi" << endl;
    	}
    
    	~Daten()
    	{
    		cout << "Bye" << endl;
    	}
    };
    
    std::auto_ptr<Daten> Do( int i )
    {
    	auto_ptr<Daten> ret( new Daten() );
    	ret->x = i;
    	return ret;
    }
    
    int main()
    {
    	auto_ptr<Daten> data = Do( 10 );
    	cout << data->x << endl;
    	return 0;
    }
    
    // Ausgabe:
    // Hi
    // 10
    // Bye
    


  • Fräger schrieb:

    Danke erstmal.
    Es geht in erster Linie um eine Vektorklasse und Operatoren, d.h. eine zusätzliche Referenz als Eingabeparameter kommt für mich nicht in Frage.
    Naja, dann kopiere ich halt vorerst mal alles.
    Danke.

    Was spricht dagegen zusätzlich eine Schnittstelle anzubieten welche es erlaubt "in place" zu arbeiten bzw. ein output Parameter zu akzeptieren?
    Dann kann man die operatoren verwenden in Fällen wo Geschwindigkeit egal ist, und wenns schnell gehen soll die alternative Schnittstelle.



  • @hustbaer:
    Darum meine ich ja auch vorerst.

    @Badestrand:
    Ist die Lösung mut auto_ptr nicht viel Performancelastiger (zumindest bei kleineren Rückgabedatenpaketen)?



  • Fräger schrieb:

    @Badestrand:
    Ist die Lösung mut auto_ptr nicht viel Performancelastiger (zumindest bei kleineren Rückgabedatenpaketen)?

    Wenn du nur einen Zeiger auf einen int zurückgibst, vielleicht. Die Rechenzeit, die beim auto_ptr verbraucht wird, ist aber sowas von gering! 🙂



  • Fräger schrieb:

    @hustbaer:
    Darum meine ich ja auch vorerst.

    aaaaaaaaaaah 💡 🙂

    Badestrand schrieb:

    Die Rechenzeit, die beim auto_ptr verbraucht wird, ist aber sowas von gering! 🙂

    Wenn man sowieso schon "new" verwenden muss dann ja, dann spielt der auto_ptr keine Rolle mehr. Bloss wenn man durch den blöden auto_ptr gezwungen wird new zu verwenden wo es nicht nötig wäre, dann ist das je nach grösse des zu kopierenden Objektes u.U. hundert- oder sogar tausendmal langsamer.

    EDIT: sorry, das klingt jetzt (durch das "den blöden auto_ptr") etwas aggressiv, ist aber nicht so gemeint. 🙂


Anmelden zum Antworten