Array als Referenz



  • Hallo
    ist es möglich einen Array als Referenz zu übergeben?
    Ich habe 2 Funktionen. In Funktion1 wird irgendwann Funktion2 aufgerufen. Dort soll dann ein int array[20] verändert werden. Nachher soll auf diesen Vektor dann in Funktion1 zugegriffen werden.
    Da ich gelesen habe, dass man globale Variablen wenn möglich vermeiden sollte wollte ich das mit einer Referenz machen

    funktion2(int& array[])...
    

    aber leider bekomme ich das nicht hin.

    Wäre nett wenn mir jemand helfen könnte und vielleicht auch noch erklären kann wieso man auf globale Variablen verzichten sollte 🙂

    Vielen Dank

    Gruß Zaus



  • Klammerung!

    void dings_intern(int *const zeiger, size_t n)
    {
      ...
    }
    
    template<size_t N>
    inline void dings(int (&arrayref)[N])
    {
      dings_intern(arrayref,N);
    }
    


  • Ok mit der richtigen Klammerung kompiliert er es jetzt, wobei ich sagen muss, dass ich das meiste von deinem Code nicht versehe 🙂

    Was mir auffällt: Wenn ich die Werte im Array in Funktion2 1 mal ändere kann ich die so später auch in Funktion 1 auslesen, wenn ich allerdings die werte in funktion2 ändere und später nochmal überschreibe so funktioniert das überschreiben irgendwie nicht...



  • Also ich hab einfach noch die Klammern in meinen Code eingefügt.

    funktion2(int (&array)[])
    

    Dann kam das Problem mit dem überschreiben.

    Ich häng hier gleich noch ne Frage dran:
    Gibt es einen Geschwindikeitsunterschied zwischen:
    1. Eine Funktion die einen int erhält und einen string zurückgibt

    string funktion(int b)
    {
       if (b>5)
       {
          return "ja";
       else
       {
          return "nein";
       }
    }
    

    2. den String vorher zu deklarieren und dann per Referenz an die Funktion zu übergeben in der er dann verändert wird.

    Gruß Zaus



  • Sry für den 3. post in Folge aber leider hab ich mich immer noch nicht registriert...
    Das erste Problem hat sich erledigt, bleibt nur noch die Frage nach der Geschwindigkeit 🙂



  • Das hängt davon ab, ob dein Compiler (N)RVO, eine Optimierung bei Rückgabewerten, kennt. Falls nein, muss der std::string unnötigerweise zwei Male kopiert werden: Einmal bei der return -Anweisung und einmal bei der Initialisierung std::string s = funktion() . In dem Falle wäre die Referenz sicher schneller.

    Aber moderne Compiler sollten diese Technik eigentlich beherrschen. Mach dir um die Geschwindigkeit bei solchen Dingen nicht zu viele Gedanken, meistens hast du andere Probleme. Achte lieber auf ein schönes Schnittstellendesign. Denn dass der Benutzer statt

    tuwas(funktion());
    

    nun

    std::string s;
    funktion(s);
    tuwas(s);
    

    schreiben muss, ist eventuell auch nicht das Wahre.



  • Zaus schrieb:

    Gibt es einen Geschwindikeitsunterschied zwischen:
    1. Eine Funktion die einen int erhält und einen string zurückgibt

    string funktion(int b)
    {
       if (b>5)
       {
          return "ja";
       else
       {
          return "nein";
       }
    }
    

    2. den String vorher zu deklarieren und dann per Referenz an die Funktion zu übergeben in der er dann verändert wird.

    Das macht keinen Unterschied. Es macht höchstens einen Unterschied, wenn das String-Objekt vorher schon Speicher für die Zeichenkette reserviert hatte, welcher dann wieder verwendet werden kann:

    void funk(int b, string & out);
    
    int main()
    {
      string temp;
      ...
      // temp-Objekt wird verwendet und behält Speicher
      ...
      funk(3,temp);
    }
    

    Wenn dann in funk die Zuweisung stattfindet und in out schon genügend Speicher besitzt, sollte es ganz flott gehen. Das, was typischerweise am meisten Zeit kostet, ist das Reservieren/Freigeben von Freispeicher. string verwendet den Freispeicher für die Zeichenketten.

    Alternativ kannst Du aber auch das hier schreiben:

    char const* funk(int b)
    {
      return (b>5) ? "ja" : "nein";
    }
    

    und es später bei Bedarf den Zeiger in ein string-Objekt verwandeln. Das klappt hier zumindest so, weil "ja" und "nein" String-Literale sind, die nicht dynamisch angelegt werden, sondern char-Arrays mit statischer Lebenszeit sind.

    Wenn Du deine Funktion nicht 1000000mal in einer inneren Schleife aufrufen willst, sollte das alles nicht so wichtig sein. Es ist aber natürlich von Vorteil zu wissen, was da hinter'm Vorhang so passiert. Das Initialisieren und Kopieren von string-Objekten kostet eben etwas Zeit. Manchmal braucht man keine Kopie, wie zB hier:

    bool dings(string s)
    {
      return !s.empty() && s[0]=='x';
    }
    

    Wenn ich diese Funktion so aufrufe:

    string t = "123";
    cout << dings(t);
    

    dann wird s eine lokale Kopie des string-Objekts t sein. Das muss nicht sein. Daher kann man auch schreiben:

    bool dings(string const & s)
    {
      return !s.empty() && s[0]=='x';
    }
    

    Aber pass-by-value ist auch nicht perse schlecht. Wenn man eine lokale Kopie braucht, ist das schon praktisch:

    string rueckwaerts(string s)
    {
      std::reverse(s.begin(),s.end());
      string ret;
      ret.swap(s);
      return ret;
    }
    

    Für einen Compiler, der unnötige Kopien wegoptimieren kann, ist diese Fassung von "rueckwaerts" optimal für eine Funktion die einen string bekommt und wieder einen zurückgeben soll.

    Ohh, bin wohl abgeschweift... 😃



  • Vielen Dank, ist echt super wie schnell und ausführlich man hier Antworten bekommt.
    Also in der Schleife wird die angesprochene Funktion bis zu 10.000 mal aufgerufen. Da daraus "in Echtzeit" Daten für eine Steuerung generiert werden müssen ist es sehr wichtig, dass es da zu keinen Verzögerungen kommt. Verwendet wird dabei Visual Studio 2005. Kommt dort (N)RVO zum Einsatz?

    Kennt sich einer von euch zufällig auch mit XML-Parsern aus und kann mir sagen wie groß bei über 1000 Aufrufen um eine XML-Datei nach einem bestimmten Attribut zu durchsuchen der Zeitunterschied zwischen TinyXML und RapidXML ist? Würde mir die Arbeit ersparen das selbst auszutesten 🙂


Log in to reply