- MultiPlus Wechselrichter Insel und Nulleinspeisung Conrad         
Ergebnis 1 bis 10 von 23

Thema: class mit übergebenen array Größen erstellen

Hybrid-Darstellung

Vorheriger Beitrag Vorheriger Beitrag   Nächster Beitrag Nächster Beitrag
  1. #1
    shedepe
    Gast
    Du bist schon ganz gut in der richtigen Richtung unterwegs.

    Ein multidimensional array in C++ ist eigentlich eine Liste von Pointer. D.h. list[0] z.B. liefert einen Pointer zurück, und auf diesem wird mit list[0][1] z.B. auf das 2. Element des Pointer zugegriffen.
    Deshalb kann man wie in Variante 1 das mit einer Schleife initialisieren.

    Variante 1
    Code:
    char * list;
    list = new char[menulen * captlen]
    Alternativ kann man auch einen außreichend großen Block Speicher allokieren.

    Variante 2
    Code:
    char ** list;
    list = new char*[menulen];
    for(int i = 0; i < captlen; i++)
    {
       list[i] = new char[captlen];
    }
    //Zugriff auf stelle x, y
    char val = list[x * captlen + y)
    Nachzulesen gibt es das z.B. hier: https://stackoverflow.com/questions/...in-c-using-new

    Ein Tipp außerdem: Solltest du das auf einem Mikrocontroller machen wollen solltest du auf new verzichten. Am PC würde ich auch auf die Arrays verzichten und stattdessen einen std::vector<std::vector<char>> list verwenden. Dann muss man nämlich den Speicher nicht von Hand aufräumen und hat dynamische Größen geschenkt bekommen.

  2. #2
    HaWe
    Gast
    Zitat Zitat von shedepe Beitrag anzeigen
    Du bist schon ganz gut in der richtigen Richtung unterwegs.

    Ein multidimensional array in C++ ist eigentlich eine Liste von Pointer. D.h. list[0] z.B. liefert einen Pointer zurück, und auf diesem wird mit list[0][1] z.B. auf das 2. Element des Pointer zugegriffen.
    Deshalb kann man wie in Variante 1 das mit einer Schleife initialisieren.

    Variante 1
    Code:
    char * list;
    list = new char[menulen * captlen]
    Alternativ kann man auch einen außreichend großen Block Speicher allokieren.

    Variante 2
    Code:
    char ** list;
    list = new char*[menulen];
    for(int i = 0; i < captlen; i++)
    {
       list[i] = new char[captlen];
    }
    //Zugriff auf stelle x, y
    char val = list[x * captlen + y)
    Nachzulesen gibt es das z.B. hier: https://stackoverflow.com/questions/...in-c-using-new

    Ein Tipp außerdem: Solltest du das auf einem Mikrocontroller machen wollen solltest du auf new verzichten. Am PC würde ich auch auf die Arrays verzichten und stattdessen einen std::vector<std::vector<char>> list verwenden. Dann muss man nämlich den Speicher nicht von Hand aufräumen und hat dynamische Größen geschenkt bekommen.
    danke,
    ich wollte es tatsächlich auf einem ESP oder ARM machen, evtl. aber auch kompatibel zu einem Raspi.
    (schön ntl, wenn es später auch auf AVRs läuft.)
    vector kenne ich noch nicht, aber für später ist es wichtig, dass ich prinzipiell auf diese Weise den Zugriff habe auf 2-dim arrays, sowohl intern als auch dann von der aufrufenden Funktion:

    this->char list[10][20]={"line0", "line1", "line2", "line3",..., "line9"};
    Serial.println(this->list[k]);

    tMenu mymenu(10,20);
    strcpy(mymenu.list[5], "5 new testline", sizeof(testline));
    mymenu.list[5][0]='>';

    also Zugriff direkt auf die 2-dim Struktur, ohne immer rechnen zu müssen
    x * captlen + y

    Wie macht man es also am besten, cross-over-Plattform-kompatibel?
    Geändert von HaWe (04.12.2018 um 09:46 Uhr)

  3. #3
    shedepe
    Gast
    Für den ESP32 kann ich leider nichts sagen.
    Deshalb erläutere ich kurz die Überlegung dahinter warum man auf einem Mikrocontroller in der Regel keinen Speicher dynamisch allokieren möchte.
    Das Problem dabei ist: Wenn man Speicher mit malloc oder new allokiert, wird dieser intern von der libc verwaltet. Diese schaut prinzipiell wo ist noch Speicher übrig bzw. wo ist genügend speicher am Stück übrig. Wenn man jetzt aber z.B. auf einem Atmega sehr wenig Speicher hat, wird dieser sehr schnell durchlöchtert wenn man häufiger Speicher reserviert bzw. wieder frei gibt. Die libc implementiert zwar Algorithmen um diesen Speicher möglichst intelligent zu verwalten, das funktioniert nur mit sowenig Speicher nicht so super bzw. kann sehr viel Performance klauen. Zudem kann man nicht zur compilezeit sagen ob der Speicher überhaupt reicht.

    Bei größeren Controllern wie dem ESP32 kann es durchaus möglich sein, dass effizient mit dynamisch allokiertem Speicher umgegangen werden kann.

    Ob es Sinn macht die Container aus der C++ Standardlib zu verwenden auf dem ESP32, müsstest du auch noch mal recherieren. Diese machen einem das Leben wesentlich leichter, kosten aber natürlich auch etwas mehr Speicher und CPU Leistung.

  4. #4
    HaWe
    Gast
    neinnein, ich habe "nur" einen esp8266, alternativ M0, M3, M4, aber es wäre ntl schön auch auf dem Raspi und auch AVR Mega oder gar Nano: grundsätzlich eben Plattform-unabhängig.
    Das mit den Löchern verstehe ich, aber es wird vorraussichtlich nicht so häufig passieren mit dem destructor, viel häufiger werden constructors nacheinander aufgerufen werden.

    Was würdest du also vorschlagen für die Erzeugung von 2-dim arrays
    - wichtig, wie gesagt, ist der direkte Zugriff auf alle einzelnen Speicherzellen beider Dimensionen, ohne so etwas wie
    x * captlen + y
    rechnen zu müssen,
    so z.B. wie bereits oben erwähnt

    tMenu mymenu(10,20);
    strcpy(mymenu.list[5], "5 new testline", sizeof(testline));
    mymenu.list[5][0]='>';

  5. #5
    shedepe
    Gast
    Mein Vorschlag wäre: Mache eine Klasse, wie du sie jetzt schon hast. Lege aber die Instanzen des Klassen auf dem Stack an.
    Also statt tMenu * mymenu = new tMenu(); lieber tMenu myMenuy;

    Dann solltest du die Größen statt über den Konstruktor lieber als C++ Template übergeben. Dann können die zur Compilezeit ersetzt werden.
    Dann kannst du dein array auch mit: char mylist[x][y] anlegen.

    Beispiel
    Code:
    template <int x_size,int y_size>
    class Menu{
         private:
             char list[x_size][y_size];
         
    
    
    };
    
    Verwendung:
    Menu<10,20> myMenu;
    Noch ein Hinweis zum Rechnen (Falls das mal relevant für dich werden sollte):
    Einfach den Zugriff in einer Methode Kapseln die das Rechnen macht und dann ist das auch gar nicht so schlimm

  6. #6
    HaWe
    Gast
    hmm, vielen lieben Dank, das klingt alles wirklich gut. Ich muss jetzt nur noch alles ineinander kriegen, tatsächlich ist dieses hier erst mein zweites C++ OOP Projekt überhaupt.

    Erstmal, ist private besser als protected? Oder geht beides? Ist protected evtl flexibler für Zugriffe von "außen" und "innen"?

    dann zu
    Also statt tMenu * mymenu = new tMenu(); lieber tMenu myMenu;
    ja: so hatte ich es ja auch vor als Instanz: tMenu myMenu;


    Das wäre jetzt, was ich aus deinen Vorschlägen verstanden habe, mit int16_t als Kompromiss zw. char und int für die sizes,
    allerdings völlig unklar wie der constructor jetzt aussehen muss , also wie genau ich den array samt seines Speicherbedarfs dynamisch erzeugen soll:

    Code:
    class tMenu{
       private :
    
           int16_t  MENULEN, CAPTLEN;      
           char list[MENULEN][CAPTLEN];
    
       public:      
        
         tMenu (int16_t menulen, int16_t captlen) // constructor
         {       
            MENULEN = menulen;
            CAPTLEN = captlen;
    
            // .... und wie weiter hier?
         }      
    
     
         ~tMenu() // destructor
         {
           // Dynamically delete the array we allocated earlier
           delete[] list ;
         }
    
    };
    Edit:
    zusätzlich rechnen möchte ich ja nicht, weder innerhalb der Klasse noch außerhalb bei Verwendung von Instanzen.
    Instanziierung würde ich auch am liebsten ohne template machen, wenn möglich, einfach per

    tMenu mymenu(10,20);

    für solche Manipulationen in main oder loop:

    strcpy(mymenu.list[5], "5 new testline", sizeof(testline));
    mymenu.list[5][0]='>';
    Geändert von HaWe (04.12.2018 um 12:43 Uhr)

  7. #7
    HaWe
    Gast
    wie muss denn also dafür der construcor für den "echten" dynamischen 2-dim array aussehen?

    denn diese beiden Methoden

    Code:
    char * list;
    list = new char[menulen * captlen]
    
    char ** list;
    list = new char*[menulen];
    for(int i = 0; i < captlen; i++)
    {
       list[i] = new char[captlen];
    }
    
    //Zugriff auf stelle x, y
    char val = list[x * captlen + y)
    scheinen ja nur jew. einen 1-dim array zu erzeugen....?

Ähnliche Themen

  1. Change member of a class from another class
    Von iciwi im Forum Arduino -Plattform
    Antworten: 1
    Letzter Beitrag: 27.08.2016, 09:45
  2. neues Byte aus Byte-Array erstellen
    Von BoondockDuck im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 4
    Letzter Beitrag: 06.09.2008, 07:53
  3. Bits in sämtlichen Größen :)
    Von squelver im Forum Allgemeines zum Thema Roboter / Modellbau
    Antworten: 0
    Letzter Beitrag: 22.11.2007, 12:02
  4. SMD-Größen für SMD-Anfänger
    Von jeybo im Forum Elektronik
    Antworten: 22
    Letzter Beitrag: 29.08.2006, 07:04
  5. Eagle - Größen
    Von BlackDevil im Forum Konstruktion/CAD/3D-Druck/Sketchup und Platinenlayout Eagle & Fritzing u.a.
    Antworten: 9
    Letzter Beitrag: 27.03.2006, 22:58

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •  

Solar Speicher und Akkus Tests