Zeiger



  • Hallo,

    @ _DocShoe_: Ich seh da keinen Sinn drin, komplizierten Code hier zu posten, wo doch die einfache Funktion swap mein Problem ganz gut erklärt.

    Nur für mich zum Verständnis:

    void swap(int *x, int *y)
    {
    int *temp = x;

    x = y;
    y = temp;
    }

    Nach Verlassen der Funktion ist x bzw der Speicherbereich, auf den x zeigt, ungültig, da das lokale temp auch darauf zeigt und nach Verlassen der Funktion der Bereich von temp und somit auch von x freigegeben wird ?



  • alti23 schrieb:

    Nach Verlassen der Funktion ist x bzw der Speicherbereich, auf den x zeigt, ungültig, da das lokale temp auch darauf zeigt und nach Verlassen der Funktion der Bereich von temp und somit auch von x freigegeben wird ?

    Nein, das stimmt nicht. Es werden nur die lokalen Zeigervariablen temp, x und y "ungueltig" bzw. vom Aufrufstack abgeraeumt. Der Speicher, auf den die Zeiger zeigen, ist davon nicht betroffen. Das ist ja u.a. der Witz an Zeigern, dass sie auf Speicher zeigen koennen, der nicht im direkten Zusammenhang mit dem aktuelle Gueltigkeitsbereich des Zeigers steht.



  • Nochmal: Du brauchst das new nicht... Ergo auch kein delete. Du brauchst keinen Platz für die Instanzen zu reservieren. Du brauchst schlicht und ergreifend nur den Zeiger. Es sei denn Du willst Werte tauschen und keine Zeiger, aber auch das wurde schn gezeigt.
    Und nur ums es nochmal ganz klar zu sagen: Der Tausch ist - so wie von dir durchgeführt - nur innerhalb der Funktion swap gültig.

    Ansonsten schau dir noch mal die Postings von Kolumbus und GyroGearloose an. Oder, wie auch schon mehrfach erwähnt, poste das konkrete Problem. Wir könnten mit Sicherheit helfen, aber nicht ohne das Problem zu kennen. Offensichlich gehst du von falschen Vorstellungen aus, oder hantierst möglicherweise mit globalen Variablen (was man vermeiden sollte)... Wissen wir eben nicht.

    Anhand des bisher gezeigten Codes läßt sich sonst nichts weiter sagen.

    Gruß KK



  • Vielen Dank für Eure Antworten.
    Es ist wohl so, dass ich da was falsch verstanden habe.
    betrachtet bitte nochmal folgenden Code und schreibt mir, ob der Zeigr y
    in main auf einen gültigen Bereich zeigt.
    Ich vermute nein !!
    Ändert sich dies, wenn ich die Zeile "delete x;" weglasse ?

    .h:
    class testclass
    {
    private:
    int *tempint;

    public:
    void testclass(void);
    void testmethod(void);
    int* gettempint(void);
    };

    .cpp:
    void testclass::testmethod()
    {
    int x = new int(5);
    tempint = x;
    delete x;
    }
    int
    testclass:gettempint(void)
    {
    return tempint;
    }

    int main()
    {
    testclass x;
    int *y;
    x.testmethod();
    y = x.gettempint();
    }



  • Hallo alt23,

    ich kann Dir nur empfehlen mal das Buch

    Die C++ Prgrammiersprache

    von Biarne Stroustrup zu lesen. ISBN 0.201-539929-6.
    Deine beiden Letzten Beiträge zeigen ausserdem, dass Du nicht genau angeschaut hast, was wir Dir vorprogrammiert haben.

    @Braunstein - Solch einen Kommentar hätte ich von Dir nicht erwartet, schade.
    Gruß Rudi



  • alti23 schrieb:

    ... Zeigr y
    in main auf einen gültigen Bereich zeigt.
    Ich vermute nein !!

    Nein. Das mag zwar funktionieren, da der Speicher so schnell nicht für eine andere Variable verwendet wird, aber grundsätzlich ist der Zustand undefiniert.
    Im gezeigten Beispiel würde es wohl funktionieren, aber mit Sicherheit nicht auf Dauer. Ein paar Speicherreservierungen zwischendurch - und es knallt...

    alti23 schrieb:

    Ändert sich dies, wenn ich die Zeile "delete x;" weglasse ?

    Ja. Denn somit wird der Speicher nicht freigegeben und die Instanz, auf die der Zeiger zeigt, behält ihre Gültigkeit. Aber du hast ein Speicherleck geschaffen... (von der wirklich unschönen Methode, y freizugeben mal abgesehen).

    Am einfachsten wäre es wohl du würdest der Klasse einen Konstruktor und einen Destruktor spendieren.

    Gruß KK

    @RudiM: Vielleicht ein bißchen schroff formuliert, aber prinzipiell hat er recht. Dein Code ist kein gültiges C++. Versuch das mal zu kompilieren. 😉



  • Danke KK, jetzt ist's klar !!



  • rudiM schrieb:

    @Braunstein - Solch einen Kommentar hätte ich von Dir nicht erwartet, schade.
    Gruß Rudi

    Dein Code war einfach völlig falsch.
    1. Die Deklaration der Funktionsparameter stimmt nicht. Dort nur einen Typ angeben und dann mehrere Parameter aufführen geht vielleicht in Pascal, aber nicht in C++.
    2. Du übergibst in der Funktion Referenzen auf int und willst denen Zeiger auf int zuweisen. Auch falsch.
    Ich wollte eigentlich nur darauf hinweisen, dass man sich den Code ansehen sollte bevor man ihn postet. Wenn es zu hart rübergekommen ist, dann entschuldige ich mich hiermit bei dir. Ok?



  • alti23 schrieb:

    Hallo,

    @ _DocShoe_: Ich seh da keinen Sinn drin, komplizierten Code hier zu posten, wo doch die einfache Funktion swap mein Problem ganz gut erklärt.

    Nur für mich zum Verständnis:

    void swap(int *x, int *y)
    {
    int *temp = x;

    x = y;
    y = temp;
    }

    Nach Verlassen der Funktion ist x bzw der Speicherbereich, auf den x zeigt, ungültig, da das lokale temp auch darauf zeigt und nach Verlassen der Funktion der Bereich von temp und somit auch von x freigegeben wird ?

    Tja, und genau da sehe ich das Problem. Du postest einen Codeschnipsel, der ein einfaches Problem kompliziert löst. Ich hätte jetzt sofort sagen können, dass du deine swap Funktion wegwirfst und stattdessen std::swap benutzt, aber vorher wollte ich noch einmal nachfragen, ob du nicht vielleicht doch etwas anderes machst, was man mit std::swap nicht lösen kann. Genausogut könnte ich keinen Sinn darin sehen, auf ein Posting zu antworten, dass das Problem nicht präzise beschreibt. Häufig sind sich Fragesteller auf Anfängerniveau über die Art des Problems nicht bewusst bzw. es fehlt Basiswissen, um das Problem zu beschreiben. Und genau aus diesem Grund möchte ich wissen, was genau du machen willst um ggf. Alternativen anzubieten.
    Nach allen Informationen, die ich jetzt habe, rate ich dir:
    Wirf deine swap Funktion weg und benutze std::swap.



  • PS:
    Mit kompliziertem Code meine ich nicht den Zitierten, sondern den aus dem Eingangsposting.



  • DocShoe schrieb:

    [...] Häufig sind sich Fragesteller auf Anfängerniveau über die Art des Problems nicht bewusst bzw. es fehlt Basiswissen, um das Problem zu beschreiben. [...]

    Ganz genau 👍 Vor nicht allzu langer Zeit war ich selbst noch blutiger Anfänger (jetzt bin ich nur noch Anfänger 😉 ) und bin immer wieder überrascht, wohin meine Ausgangsfragen führen... Das kann man aber nur erleben, wenn man mit seinen Quelltexten und Gedanken nicht hinterm Berg hält und nicht zu faul ist ordentlich (auf dem derzeitigen Niveau vollständig und durchdacht) zu posten. Ausserdem sollte man bereit sein den Hinweisen der erfahrenen Nutzer nachzugehen, auch wenn man im 1. Moment keinen Bezug zur gefragten Problematik herstellen kann.
    JM2C 🙂



  • Hallo,

    @Kolumbus: Du warst der Lösung wohl am nächsten, ich war wie so oft voreilig.

    void swap(int *&x, *&y) 
    { 
        int *temp;
        temp = x; 
        x = y; 
        y = temp; 
    }
    

    ich hab die beiden Sternchen wohl selbst nicht beachtet. Schande über mich.
    @ Braunstein: is ok.
    Gruß Rudi



  • Da fehlt noch ein int.
    So ist es dann OKer. 😉

    void swap(int *&x, int *&y)
    {
        int *temp = x;
        x = y;
        y = temp;
    }
    


  • Oops, i did it again..............

    Aber das bringt mich auf die Frage: Wieso schafft es der Compiler mehrere Variablen den gleichen Typs anlegen zu lassen:

    void f()
    {
    int a,b,c,d;
    
    usw.
    }
    

    aber nicht innerhalb eines Funktionsaufrufes? Wäre doch praktisch, oder?
    Gruß, der schreibfaule Rudi



  • rudiM schrieb:

    aber nicht innerhalb eines Funktionsaufrufes?

    Innerhalb eines Funktionsaufrufes darfst du ohnehin nichts deklarieren.

    Daß du in Funktionssignaturen (auf die du dich vermutlich beziehst) nicht mehrere Variablen des gleichen Typs ohne erneute Nennung desselben deklarieren kannst, dürfte darin begründet sein, daß dir in deklarativem Kontext zwei Terminalsymbole zur Verfügung stehen (' , ' und ' ; '), in der Funktionssignatur jedoch nicht. Der Compiler betrachtet Variablendefinitionen in Funktionssignaturen insofern nicht gesondert, nur eben mit einem anderen Terminalsymbol. Auch in normalem Kontext geht folgendes nicht:

    int a, b, float c;
    

    In diesem Kontext trennt ' ; ' Deklarationen und ' , ' Bezeichner. In einer Funktionssignatur trennt ' , ' Deklarationen, und ' ; ' ist nicht erlaubt. Wäre das anders, so stünde auch einer Mehrfachverwendung von Typen wie in Pascal nichts im Wege:

    void foo (int a, b; float c) { ... }
    


  • Hi,

    zu dem viel geliebten Thema Zeiger und gerade dem Beispiel in diesem Thread habe ich noch eine Frage. Mir sind folgende 2 Versionen bekannt:

    Vertauschen von 2 Variablen mittels Zeiger

    void swap(int *x, int *y) 
    { 
     int temp = *x; 
     *x = *y; 
     *y = temp; 
    }
    

    Vertauschen mittels Referenzen

    void swap(int &x, int &y) 
    { 
     int temp = x; 
     x = y; 
     y = temp; 
    }
    

    Doch was bedeutet diese Version ? Einen Zeiger auf eine Referenz ?

    void swap(int *&x, int *&y) 
    { 
     int *temp = x; 
     x = y; 
     y = temp; 
    }
    

    Kann mir das bitte jemand erklären, macht das Sinn, das so zu tun ? Vorteile ?



  • Bei den oberen beiden Versionen werden die Werte getauscht (auf die die Zeiger zeigen). Bei der letzten Version werden die Zeiger getauscht (die Werte werden nicht geändert, dafür zeigen die Zeiger nun jeweils auf den anderen Wert).

    Gruß KK



  • Vielen Dank für Deine Erklärung, KK. Um das Ganze noch abzurunden, kannst Du mir noch sagen wann man welche Methode benutzt, also wäre die Variante 3 deutlich schneller als die andern zwei oder ist das egal ?



  • Variante 3 macht etwas ganz anderes als die anderen beiden Varianten (Zeigertausch wie schon erklärt). Varianten 1 und 2 sind ebenfalls nicht äquivalent einsetzbar da der Aufrufsyntax unterschiedlich ist.
    Was habt ihr alle gegen std::swap? 🙂


Anmelden zum Antworten