Problem bei Operatorüberladung [] und =



  • manni66 schrieb:

    Warum legst du test1 mit new an? Dann muss es (*test1)[5] heissen.

    Danke, manchmal bin ich echt zu blöd. Klar muss ich (*test1)[5] so drauf zugreifen. Ist ja ein Zeiger. Und natürlich macht es in meinen einfachen Beispiel keinen Sinn test1 mit new anzulegen. Aber später schon ;).

    manni66 schrieb:

    Zum Lesen kannst du den Operator verwenden, zum Schreiben müsste er aber eine Referenz liefern.

    Und das kann ich nicht. Ist ja ein einfaches Byte was ich aus meinem externen RAM hole.



  • Neo87 schrieb:

    manni66 schrieb:

    Zum Lesen kannst du den Operator verwenden, zum Schreiben müsste er aber eine Referenz liefern.

    Und das kann ich nicht. Ist ja ein einfaches Byte was ich aus meinem externen RAM hole.

    Wieso soll man ein einfaches Byte nicht per Referenz übergeben können?
    Meinst du, dass du eine komische Funktion benutzen musst um an den externen RAM ranzukommen und deshalb dieses Byte keine Adresse hat, ähnlich zu Bytes auf der Festplatte?
    Dann kann vielleicht ein Wrapper helfen:

    struct ByteWrapper{
        operator uin8(){ //zum Lesen, damit sich ein ByteWrapper wie ein uint8 verhält
            return byte;
        }
        ByteWrapper &operator= (uint8 b){ //damit du ein ByteWrapper wie ein normales uint8 beschreiben kannst
            byte = b;
            writeByte(adresse, byte);
            return *this;
        }
        ByteWrapper(unsigned int adresse){
            byte = readByte(adresse);
        }
    private:
        uint8 byte;
        unsigned int adresse; //im externen RAM
    };
    
    struct ExternerRam{
        ByteWrapper operator[] (unsigned int adresse){
            return ByteWrapper(adresse);
        }
    };
    
    //zu benutzen:
    ExternerRam eram;
    void tuwas(uint8);
    tuwas(eram[42]); //ließt den externen RAM
    eram[5] = 17; //schreibt in den externen RAM
    

    Es gibt da noch das Problem, dass die letzte Zeile von Adresse 5 liest, was Quatsch ist. Das kriegt man aber auch noch irgendwie weg.

    Ich hoffe mal meine Glaskugel lag nicht völlig falsch.



  • sry, dass ich mich erst jetzt melde, ich hatte das ganze schon ad acta gelegt. Aber ja, deine Glaskugel hat vollkommen recht. Da der avr-g++ leider nur 16bit Pointer verwendet ist er nicht in der Lage die externen 512kB anzusprechen.
    Also komme ich nur via Inline Assambler an den externen RAM.

    Nen Wrapper zu verwenden ist da natürlich ne super Idee. Wäre ich alleine nie drauf gekommen.
    Nur leider musste ich mein Projekt auf Grund von Platzmangel ein wenig umstellen, so das ich von solchem Luxus zurzeit nur noch träumen kann.

    Aber trotzdem danke für den Tipp.



  • Neo87 schrieb:

    manni66 schrieb:

    Warum legst du test1 mit new an? Dann muss es (*test1)[5] heissen.

    Und natürlich macht es in meinen einfachen Beispiel keinen Sinn test1 mit new anzulegen. Aber später schon ;)..

    Ähm, nur um was klar zu stellen:
    Es macht nie Sinn etwas mit new[] anzulegen.



  • Nathan schrieb:

    Es macht nie Sinn etwas mit new[] anzulegen.

    Es macht in einem µC auch nie Sinn, new[] indirekt (z.B. durch std::vector) zu verwenden.



  • mükro schrieb:

    Nathan schrieb:

    Es macht nie Sinn etwas mit new[] anzulegen.

    Es macht in einem µC auch nie Sinn, new[] indirekt (z.B. durch std::vector) zu verwenden.

    natürlich macht kapselung keinen sinn! wo sind wir denn hier? bei c++?????



  • Nathan schrieb:

    Es macht nie Sinn etwas mit new[] anzulegen.

    Ja, nee ist klar! 🙄



  • knivil schrieb:

    Nathan schrieb:

    Es macht nie Sinn etwas mit new[] anzulegen.

    Ja, nee ist klar! 🙄

    dann nenn mir einen einzigen fall, in welchem new[] einem stl-container vorzuziehen ist



  • Beim Backend eines selbstgeschriebenen Allokators. 🙂



  • Schreib mal ein Beispiel wo man bereits einen Konstruktoraufruf braucht und nicht nur rohen Speicher benötigt.



  • Skym0sh0 schrieb:

    Beim Backend eines selbstgeschriebenen Allokators. 🙂

    Dort tust du aber nicht new[] verwenden, sondern operator new()

    PS:
    ich gebe Nathan recht: new[] braucht man nicht.

    (und jede Regel hat eine Ausnahme - aber um ehrlich zu sein, ich habe new[] noch nie in production Code verwendet).



  • Wer hat denn hier von new[] gesprochen?

    Ich habe doch ledigtlich ein Objekt mit new angelegt. Dieses Objekt enthält nichts weiter als eine Speicherbereich auf meinem externen RAM(da ich diesen nur per inline-Assambler ansprechen kann). Jetzt wollte ich doch ledigtlich auf die einzeilnen Elemente per objekt[index] zugreifen, statt per objekt->readbyte(index).



  • knivil schrieb:

    Nathan schrieb:

    Es macht nie Sinn etwas mit new[] anzulegen.

    Ja, nee ist klar! 🙄

    So pauschal meinte er das nicht. Es geht um Code, in dem Bausteine um new[] zu umgehen bereits unmittelbar vorhanden sind. Einen STL-Container in einem Allokator zu verwenden ist sinnfrei, da dieser den allozierten Speicher nicht besitzt. Aber sobald STL-Container definiert sind, also Konstrukte die (im Sinne von RAII) den Speicher besitzen, ist rohe Speicherallozierung ein Tabu.

    Dort tust du aber nicht new[] verwenden, sondern operator new()

    Shade, dieser Scherzkeks. 🙂

    ⚠ Es ist nämlich ::operator new() . ~Zumindest beim Standardallokator.~



  • Sone schrieb:

    [Sonntagspredigt]

    Wie immer ignorieren wir fleissig mindestens einen nebensächlichen Fakt. Hier um einen Microcontroller mit 512kb(!) RAM handelt. Auf Microcontrollern verwendet man besser keine C++-Standardbibliothek (wobei sie oft auch gar nicht vorhanden ist. Muss sie auch nicht)



  • facepalm schrieb:

    Sone schrieb:

    [Sonntagspredigt]

    Wie immer ignorieren wir fleissig mindestens einen nebensächlichen Fakt. Hier um einen Microcontroller mit 512kb(!) RAM handelt. Auf Microcontrollern verwendet man besser keine C++-Standardbibliothek (wobei sie oft auch gar nicht vorhanden ist. Muss sie auch nicht)

    Habe ich gesagt, dass man immer die STL verwenden soll? Ich habe gesagt, man soll nie new[] roh verwenden! Auf einem Mikrokontroller wird man auch irgendwie RAII nehmen - wenn man das nicht tut, dann kann man gleich zu C wechseln.

    P.S.: Mein Mikrokontroller hat 2kB RAM. 512 sind ziemlich viel. Man sieht, du hast Erfahrung mit solchen Zahlen (!). 🙄



  • facepalm schrieb:

    Sone schrieb:

    [Sonntagspredigt]

    Wie immer ignorieren wir fleissig mindestens einen nebensächlichen Fakt. Hier um einen Microcontroller mit 512kb(!) RAM handelt.

    Nicht ganz 😉 der eigentliche Mikrocontroller hat nur 16kb RAM, ich habe aber 512kb externen SRAM am EBI hängen!
    Wie schon geschrieben kann der AVR-G++ den aber nicht verwalten, dar er nur mit 16bit Pointern arbeitet. Ich muss mich also um die 512kb von Hand kümmern und kann dort nur "Werte" ablgegen und keine Objekte erzeugen (Jedenfalls wüsste ich nicht wie?).
    Deswegen meine ExtRAM-Klasse, diese legt im internen RAM ein Objekt an welches die Speicheradresse zum externen RAM beinhaltet. Dabei organiesiere ich meinen externen RAM wie einen Heap. Ich kann also Speicher reservieren und wieder freigeben. Ich wollte jetzt ledigtlich darauf wie auf ein Array, per [index], zugreifen.

    P.S. Und man kann C++ sehr wohl sinnvoll auf einem Mikrocontroller einsetzten. Gerade bei größeren Projekten wie meinem. Touchscreen, Bluetooth, 96 LEDs mit 12bit-PWM, 4x32Mbit-Flash, diverse Sensoren.
    Gerade bei der GUI möchte ich nicht auf den Komfort verzeichten mal eben per new UIButton mir einen Button zu erzeugen 🙂



  • Gerade bei der GUI möchte ich nicht auf den Komfort verzeichten mal eben per new UIButton mir einen Button zu erzeugen

    Ja, aber ich bete dafür, dass du Smart-Pointer verwendest.



  • Sone schrieb:

    Ja, aber ich bete dafür, dass du Smart-Pointer verwendest.

    Nein, warum sollte ich?



  • Neo87 schrieb:

    Sone schrieb:

    Ja, aber ich bete dafür, dass du Smart-Pointer verwendest.

    Nein, warum sollte ich?

    Naja, wenn du immer weiter mit new allozierst, ohne den zuvor angeforderten Speicher freizugeben, dann frage ich mich, ob dir der Speicher nicht irgendwann ausgeht.
    Der Controller kann schließlich nicht ahnen, wann du den Speicher nicht mehr benötigst und ihn automatisch freigeben. Oder doch?



  • Naja, also ich mache das so, dass ich jedem UIElement(Button, Slider, Image,...) ein Window zuweise. Das Window enthält dabei alle Referenzen auf die einzelnen UIElemente. Lösche ich jetzt das Window kümmert es sich auch darum das alle ihm zugewiesenen Elemente wieder freigegeben werden.
    Das window kümmert sich außerdem um das Zeichnen auf dem Display und ruft die entsprechenden Callback-routinen auf wenn ein "Touch" erkannt wurde.


Anmelden zum Antworten