Pointer erst in einer Funktion zum Leben erwecken?



  • Hallo allerseits,

    ich denke was ich tun möchte wird direkt durch folgenden Code klar:

    #include <iostream>
    
    void CharTest(char *Pointer)
    {
        Pointer = new char[3];
        Pointer[0] = 'H';
        Pointer[1] = 'i';
        Pointer[2] = '\0';
    }
    
    int main()
    {
        char *Message;
        CharTest(Message); //Autsch -> Unbehandelte Ausnahme -> Zugriffsverletzung
        std::cout << Message;
        delete[] Message;
        std::cin.get();
    }
    

    Das das so nicht funktioniert ist mir klar, sonst würde ich hier nicht schreiben.
    Mich interessiert, was geändert werden muss, damit mein Zeiger am Ende "Hi" enthält.

    Ich freue mich über jede Hilfe.

    lg Max



  • #include <iostream> 
    
    void CharTest(char*& Pointer) //< hier
    { 
        Pointer = new char[3]; 
        Pointer[0] = 'H'; 
        Pointer[1] = 'i'; 
        Pointer[2] = '\0'; 
    } 
    
    int main() 
    { 
        char *Message; 
        CharTest(Message); //Autsch -> Unbehandelte Ausnahme -> Zugriffsverletzung 
        std::cout << Message; 
        delete[] Message; 
        std::cin.get(); 
    }
    


  • Ey verflucht, ja man, danke! 🙂

    Ich bitte aber um ne Erklärung des Vorgangs, wenns möglich ist...

    lg Max



  • Du hast den Pointer by-value übergeben.

    new änder den Wert des Pointers selbst, die Änderung bekommt main() natürlich nicht mit.

    Nach meiner Änderung wird nicht mehr der Pointer direkt übergeben sondern eine Referenz auf den Pointer. Ist ähnlich wie das konzept des Pointer selbst, die main() bekommt jetzt mit, dass new den Wert des Pointers geändert hat.

    Zum Nachschlagen im Lehrbuch/Tutorial: operator new, referenz 😉



  • Vielen herzlichen Dank!

    lg Max



  • char*& Pointer

    Wobei sich da einem schon die Zehennaegel aufrollen !
    Also beim lesen von sowas wird niemand gluecklich !

    entweder man bleibt aus driftigen Gruenden beim C Interface und verzichtet auf die referenz zugunsten eines pointers of pointers ...
    char ** pPointer
    da fuehlen sich zumindest die C Veteranen wohl dabei 🙂

    C++ benutzt eigentlich ganz andere Techniken ... da waer wohl eher
    std:string CharTest();
    oder
    void CharTest(std::string & rValue);

    die bessere Wahl.

    Wenn man scho lernt, sollt man sich auch gleich bissi mit "ordentlichen" design auseinandersetzen 🙂

    Ciao ...



  • RHBaum schrieb:

    ...entweder man bleibt aus driftigen Gruenden beim C Interface und verzichtet auf die referenz zugunsten eines pointers of pointers ...
    char ** pPointer
    da fuehlen sich zumindest die C Veteranen wohl dabei 🙂 ...

    Auch wenn es unter C++ häufig bessere Möglichkeiten gibt, ist der Vorzug ** gegenüber *& meines Erachtens schlecht. Mag sein das C-Veteranen mit Doppelzeigern besser klar kommen, aber auch wenn eine Zeigerreferenz ungewöhnlich aussieht muss man sich hierbei wenigstens nicht um mehrfache Indirektionen kümmern (was auch C++ Neulingen dann etwas zugute kommt, nicht jeder ist ein Veteran der ersten Stunde).

    cu André



  • was auch C++ Neulingen dann etwas zugute kommt, nicht jeder ist ein Veteran der ersten Stunde

    Grade bei Neulingen ....

    rohe pointer sollten in c++ soweiso eher vermieden werden. ned immer moeglich klar.
    Aber wo muss ich den die referenz aufn pointer uebergeben ? ... eigentlich nur wenn ich object irgendwo erzeuge und das resultat zurueckgebe. Ausser in Objectfactories eher schlechtes design oder ?

    Grad da sollte man Achtungszeichen setzen ... und den Neulingen grad das leicht zu machen, iss wohl eher der falsche weg.

    Auch wenn es unter C++ häufig bessere Möglichkeiten gibt, ist der Vorzug ** gegenüber *& meines Erachtens schlecht

    doch grade deshalb. Weil man expliziet sich schon entscheiden sollt zwischen c++ und c ... und "schlechtere" "Fehlerandfaelligere" Möglichkeiten zu benutzen statt optimalere soll weh tun 🙂

    Implementiert man obige funktion sauber, wird sich die referenz auf den Zeiger eh aufloesen. Wer in ernsthaften Projecten das da oben durchgehen laesst ... ich weiss ned.
    Weiss ned wie Du programmierst, aber referenz auf Zeiger kommt bei uns in reinem C++ fast gar ned vor.
    Vorkommen koennt es eher in zusammenarbeit mit C Api's .... und da gibt es bessere loesungen. Aber zumindest ein typedef auf den char * in so ner umgebung waer angebracht, womit das *& verschwinden wuerd, und jeder der den code liest ahnen kann, das ich das da bewusst gemacht hab.

    Das *& sieht zum .... aus, und das ist auch gut so ... weil wenn man sowas liest, sollten schon irgendwelche Vorgaenge im Hinterkopf ausgeloest werden !

    Ciao ....



  • RHBaum schrieb:

    Weiss ned wie Du programmierst, aber referenz auf Zeiger kommt bei uns in reinem C++ fast gar ned vor.

    Ich bin leider davon abhängig was mir geliefert wird, und das wir viele Altlasten im Programm haben (zudem sind die DLL-Schnittstellen komplett C). An diesen Stellen befinden sich noch so schöne Konstrukte wie Doppelzeiger, Dreifachzeiger oder ähnliches.

    RHBaum schrieb:

    Aber zumindest ein typedef auf den char * in so ner umgebung waer angebracht, womit das *& verschwinden wuerd, und jeder der den code liest ahnen kann, das ich das da bewusst gemacht hab.

    Das Typedef verbirgt aber in dem Fall ggf. einen Sachverhalt den du manchmal wissen musst...

    RHBaum schrieb:

    Das *& sieht zum .... aus,

    Nicht schlimmer als ein Doppelzeiger, und einfacher in der Anwendung.

    Nochmal: Grundsätzlich sind Doppelzeiger und ähnliche Konstrukte meist ein Zeichen das es in C++ besser geht (in meinen privaten Code wüsste ich keine einzige Anwendung), nichst desto trotz sollte man hier jedoch entscheiden was für die Anwendung angenehmer ist. Du ziehst den Doppelzeiger, ich die Zeigerreferenz vor. Aber grundsätzlich *& aus Ästhetischen Gründen für schlecht zu deklarieren finde ich unsinnig (Die Referenzsyntax erleichtert imho vieles).

    cu André



  • RHBaum schrieb:

    ...
    Aber wo muss ich den die referenz aufn pointer uebergeben ? ... eigentlich nur wenn ich object irgendwo erzeuge und das resultat zurueckgebe. Ausser in Objectfactories eher schlechtes design oder ? ...

    😕

    Also für mich bedeutet "&" (non-const) in einer Parameterleiste immer "ist verpflichtender Output-Parameter" ... und das unabhängig vom Typen. Denn

    template <typename T>
    int f(T& out);
    

    soll ja auch für Zeiger/Iteratoren funktionieren ...

    Also ich habe eine Menge Referenzen in meinem Code ... auch auf Zeiger.
    Zum Beispiel in Konstruktionen wie:

    size_t find_elem_with_pos(int val, int const* & elem) {
       elem = 0;
       size_t ret = 0;
    
       static int const values[] = { 0, 2, 15, 19 };
       static size_t const* const end = &values[4];
       int const* pos = find(&values[0], end, val);
       if(pos != end) { 
          elem = pos;
          ret = pos - &values[0]/sizeof(int);
       }
       return ret;
    }
    

    Kann man bestimmt netter (exception safety, ...) schreiben, aber die Zeigerreferenz braucht man trotzdem.

    Gruß,

    Simon2.



  • Nicht schlimmer als ein Doppelzeiger, und einfacher in der Anwendung.

    Ich finds schlimmer ...

    Das Typedef verbirgt aber in dem Fall ggf. einen Sachverhalt den du manchmal wissen musst

    wie du selbst sagst, bei reinem C++ isses eher schlechtes design. Bei verwendung von C-Apis manchmal notwendig. Aber genau da kann und sollt man doch typedeffen (oder templates halt), das die Typen handlicher werden ?

    seh ich schon nen unterschied.

    Unter C war nen Doppelzeiger meist immer ... ich konstruier(dynamisch) Dir was und gebs dir als Parameter zurueck. Selbst in C nicht immer die beste Wahl.
    Normal sollte man das in C++ nie machen. Selbst wenn man unter C++ mit ner C-Api zusammenerbeiten muss braucht man das nie selber.

    Was aber oefters vorkommt, wie simon2 schreibt, ist das man nen von C geerbter Typ, der nen Zeiger ist, irgendwie gleich wie ne normale klasse/POD behandelt werden soll, weil er sich wie die klasse/POD verhaelt (oder andersrum, iteratoren sind nen beispiel).
    Aber grad da erhoeht nen typedef doch die leserlichkeit ungemein ....

    Ich verwend auch (impliziet) Referenzen auf Zeiger ... aber zwischen
    foo(void * & context)
    und
    typedef void * Handle; //(irgendwo zentral)
    foo(Handle &)

    @Simon2
    Dein beispiel liesst sich aber schon wie als haettest nen template aufgeloest 🙂
    Wenn man da keine typvarianz brauch, wuerde man das schon anders implementieren oder ?

    Also ich hab seit ner genzen weile *& nie mehr benutzt, doppelpointer eher sehr selten. Und ich hab ne menge mit C-API's zu tun und implementier teilweisse auch C Schnittstellen.

    Ciao ...



  • Hi,

    mir geht's darum, dass Zeiger nicht nur für die dynamische Erzeugung gebraucht werden, sondern auch als "optionale Verweise" (deswegen hier die Erwähnung von "Iteratoren") auf Bestehendes (also ohne "Erzeugung") verwendet werden.
    Und in dieser Funktion sehe ich da nichts Ungewöhnliches, solche Parameter per Referenz zu übergeben (z.B. wenn man keinen Returncode verwenden will oder aufgrund der Semantik nicht kann).

    Gruß,

    Simon2.


Log in to reply