Zeiger



  • Hallo,

    ich bin ein Anfänger und habe eine für euch wohl leicht zu beantwortende Frage!?
    Folgender Code:

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

    temp = x;
    x = y;
    y = temp;

    delete temp;
    }

    Wie kann ich den Zeiger temp löschen, ohne aber den Speicherbereich, auf den er zeigt, durch delete freizugeben. So wie der Code da steht, zeigt x ja nach Verlassen der Funktion auf einen ungültigen Bereich
    Diese Funktion selber ist nicht mein Problem, soll nur der Veranschaulichung dienen.

    MfG alti



  • Den Zeiger selbst brauchst/kannst du nicht loeschen. Du kannst nur den Speicher freigeben, auf den der Zeiger zeigt. Wenn du das nicht willst, dann lass das delete weg.



  • Wenn du diese swap-Funktion ernsthaft benutzen moechtest, dann solltest du sie anders implementieren, denn folgendes ist falsch:

    • Zuerst deklarierst du einen Zeiger auf einen int und weist im neu allozierten Speicher auf dem Heap zu
    • Dann weist du dem Zeiger aber eine andere Speicherstelle zu, naemlich die, auf die x zeigt, und verlierst auf diese Weise deine einzige Referenz auf den allozierten Speicher, sodass du ihn nicht mehr freigeben kannst
    • Danach laesst du x auf das Ziel von y zeigen und dann y auf das Ziel von temp (dem urspruenglichen Ziel von x)
    • Du hast dann nur die Zieladressen der beiden lokalen Zeiger x und y vertauscht, aber nicht die Werte an diesen Zieladressen
    • Zuletzt gibst du den Speicher frei, auf den temp zeigt, also den auf den x urspruenglich gezeigt hat. Das kann zu undefiniertem Verhalten fuehren, wenn dieser Speicher nicht auf dem Heap liegt

    Implementiere temp stattdessen als normale lokale Variable und dereferenziere die Zeiger x und y, um ihre Werte (nicht Zieladressen) zu tauschen:

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


  • danke für die schnellen Antworten ...
    Die swap-Funktion kommt im meinem Code eigentlich gar nicht vor, soll nur demonstrieren, dass in einer lokalen Funktion mal 2 Zeiger auf 1 Bereich zeigen, wovon nach dem Verlassen der Funktion der eine wieder gelöscht werden kann/wird (temp). Nur wie, ohne den Speicherbereich von x ebenfalls freizugeben?

    An GyroGearloose: Ich will Zeiger und nicht die Speicherbereiche, auf die sie zeigen, tauschen. Das new in der Deklaration sparen wir uns auch noch, ändert doch aber nix daran, dass temp und somit x nach Verlassen der Funktion zerstört wird !?

    MfG alti



  • Was genau ist denn das Problem bzw. was willst du machen? Lokale Zeiger sind - wie alle lokalen Variablen - solange vorhanden, wie ihr Gueltigkeitsbereich gilt. Du kannst sie nicht eigenmaechtig "loeschen" oder zerstoeren.



  • ist doch nicht so schwer Zeiger zu tauschen, geht fast genauso wie deren Inhalte:

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

    Durch den Adressoperator & bekommst du die Adresse des Zeigers x und y ( also einen Zeiger auf den Zeiger ), und kannst so deren Inhalt tauschen. Die Speicherbereiche selbst werden nicht verändert.
    Gruß Rudi



  • Vielleicht postest du mal ein Stück Code deiner realen Anwendung, um das Problem zu demonstrieren. Oft führen die Antworten am Ziel vorbei, weil man ein Stück Code präsentiert, das ein ähnliches Problem zeigt wie das, was man hat, und dann auch nur Antworten auf das gepostete Problem bekommt.
    Also, was genau soll deine Funktion tun und wobei genau hast du Probleme?



  • rudiM schrieb:

    ist doch nicht so schwer Zeiger zu tauschen, geht fast genauso wie deren Inhalte:

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

    Welche Programmiersprache ist das? 🙂
    Nach C++ sieht das nicht aus (zumindest kein gültiges).



  • Hallo,

    wenn die Typen der zu vertauschenden Zeiger feststehen und gleich sind, lautet das Stichwort Zeigerreferenz; Folgendes habe ich getestet:

    // *.h
    private:
       void ZeigerSwap(unsigned char *&, unsigned char *&);
    
    // *.cpp
    void TFormTest::Button1Click(TObject *Sender)
    {
       Edit1->Text= "";
       unsigned char TestArrayX[2]= { 0x00, 0x58 }, TestArrayY[2]= { 0x00, 0x59 };
       unsigned char *pTestX= &TestArrayX[1], *pTestY= &TestArrayY[1];
       ZeigerSwap(pTestX, pTestY);
       Edit1->Text= AnsiString::StringOfChar((char)*pTestY, 1);
    }
    
    void TFormTest::ZeigerSwap(unsigend char *&X, unsigned char *&Y)
    {
       unsigned char *Temp= X;
       X= Y;
       Y= Temp;
    }
    

    Ergebnis: Nach Betätigen von Button1 wird auf Edit1 das X ausgegeben, die Zeiger wurden also vertauscht 😉

    MfG



  • 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 🙂


Anmelden zum Antworten