mikrocontroller.net

Forum: Compiler & IDEs Membery-Array Größe einer Klasse im Konstruktor setzen


Autor: Wolfgang Ketterer (Firma: Neutron Mikroelektronik GmbH) (wollekette)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo alle zusammen,

ich habe in einem avr Mikrocontroller c++ Projekt eine Klasse mit einem 
Array als Member. Jetzt möchte ich die Größe des Arrays im Konstruktor 
festlegen. Also für jede Instanz anders.

Nachdem ich jetzt erfahren habe, dass weder der c++ Ansatz mit new [] 
bzw. free noch die Verwendung von malloc bei avr funktioniert, habe ich 
keine Ahnung, wie ich so was umsetzen soll. Hier etwas Code als Beispiel 
zur Verdeutlichung.
typedef struct
{
    int a;
    int b;
} element_t;

class ElementsQueue 
{
    element_t items[42];
};

Ich möchte jetzt beim Instanziieren die 42 festlegen. Also per 
Konstruktor. Und ich stehe völlig auf dem Schlauch, wie man sowas 
umsetzt. Kann mir da jemand einen Tipp geben?

Autor: Felix U. (ubfx)
Datum:

Bewertung
-1 lesenswert
nicht lesenswert
Wolfgang K. schrieb:
> dass weder der c++ Ansatz mit new []
> bzw. free noch die Verwendung von malloc bei avr funktioniert

Das funktioniert sogar sehr gut. Du musst dann halt nur noch 
sicherstellen, dass du das Array nicht über seine Grenzen hinaus 
indizierst.
class ElementsQueue 
{
    element_t *items;

    ElementsQueue(unsigned n)
    {
        items = new element_t[n];
    }
};

Wenn du jetzt aber darauf hinaus willst, dass man zur Laufzeit damit 
rechnen muss, dass einem der RAM ausgeht, dann lässt sich dieses Problem 
nicht beheben. Da müsstest du dann zu Beginn den ganzen notwendigen 
Speicher allozieren und deine Objekte anlegen.

: Bearbeitet durch User
Autor: Oliver S. (oliverso)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die dann auftretenden Fehlermeldungen löst dieser Beitrag:

http://www.avrfreaks.net/forum/avr-c-micro-how?page=all

Oliver

Autor: Markus F. (mfro)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
möglicherweise ein potentieller Kandidat für ein Klassen-Template:
template <size_t size> struct element_queue
{
    struct element & operator [](int index) { return items[index]; };

    struct element items[size];
};

...

    struct element_queue<10> elements;

    elements[7].a = 4711;
...

Autor: Wolfgang Ketterer (Firma: Neutron Mikroelektronik GmbH) (wollekette)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Oh mann, ich hätte geschworen, das genau so probiert und eine 
Fehlermeldung bekommen zu haben, von wegen gcc doesnt support ...
Aber da das letzte Woche war... Egal. Jetzt geht's jedenfalls.
free() funktioniert dann wohl auch?

Vielen Dank auf jeden Fall.

Autor: Scott Meyers (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Was stellt Deine Firma her? (Nur damit ich die Produkte meiden kann ...)

Autor: Felix U. (ubfx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja free funktioniert auch. Du kannst natürlich die new[] und delete[] 
Wrapper auch einfach weglassen und direkt mit malloc/free arbeiten. 
Richtig Sinn macht die Unterscheidung ja sowieso erst mit Exceptions.

Autor: Wolfgang Ketterer (Firma: Neutron Mikroelektronik GmbH) (wollekette)
Datum:

Bewertung
2 lesenswert
nicht lesenswert
Scott Meyers schrieb:

> Was stellt Deine Firma her? (Nur damit ich die Produkte meiden kann ...)

Systeme zur Verwaltung irrelevanter Postings in Internetforen. Drum muss 
die Queue ja auch in ihrer Größe anpassbar sein ;-)

Autor: Scott Meyers (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Du schreibst C++-Code und willst malloc()/free() verwenden????

Dann schau doch mal nach dem Unterschied zwischen new/delete und 
malloc()/free()!

Autor: Rolf Magnus (rmagnus)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Felix U. schrieb:
> Ja free funktioniert auch. Du kannst natürlich die new[] und delete[]
> Wrapper auch einfach weglassen und direkt mit malloc/free arbeiten.
> Richtig Sinn macht die Unterscheidung ja sowieso erst mit Exceptions.

Nein. Das wesentliche ist, dass malloc nur den Speicher reserviert, 
während new[] auch die ggf. nötige Initialisierung (z.B. 
Konstruktor-Aufrufe) macht.

Autor: Rufus Τ. Firefly (rufus) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Korrespondierend ruft delete den Destruktor (~) der freigegebenen 
Objekte auf, was mit free nicht erfolgt.

Bei einfachen Datentypen (char, int, float etc.) gibt es da keinen 
Unterschied, aber bei Klassen sehr wohl.

Autor: M.K. B. (mkbit)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich würde den Beitrag von Felix U. noch ergänzen:
class ElementsQueue
{
    element_t *items;

    ElementsQueue(unsigned n)
    {
        items = new element_t[n];
    }

    ~ElementsQueue()
    {
        // wichtig, damit der Speicher auch wieder freigegeben wird
        delete[] items;
    }
};

Autor: Rolf Magnus (rmagnus)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
M.K. B. schrieb:
>     ~ElementsQueue()
>     {
>         // wichtig, damit der Speicher auch wieder freigegeben wird
>         delete[] items;
>     }
> };

Dann aber auch um Copy-Konstruktor und Zuweisungsoperator kümmern! Also 
entweder =delete oder korrekt implementieren.

Autor: Wilhelm M. (wimalopaan)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Rolf M. schrieb:
> M.K. B. schrieb:
>>     ~ElementsQueue()
>>     {
>>         // wichtig, damit der Speicher auch wieder freigegeben wird
>>         delete[] items;
>>     }
>> };
>
> Dann aber auch um Copy-Konstruktor und Zuweisungsoperator kümmern! Also
> entweder =delete oder korrekt implementieren.

In modernem Cpp kein expl. new/delete mehr. In diesem Fall wäre der 
std::unique_ptr das richtige. Dann hat man auch das richtige 
default-Verhalten bzgl. copy/move.

Autor: Rolf Magnus (rmagnus)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wilhelm M. schrieb:
> In modernem Cpp kein expl. new/delete mehr. In diesem Fall wäre der
> std::unique_ptr das richtige. Dann hat man auch das richtige
> default-Verhalten bzgl. copy/move.

Gibt es den denn auf dem AVR?

Autor: mh (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wilhelm M. schrieb:
> In diesem Fall wäre der
> std::unique_ptr das richtige. Dann hat man auch das richtige
> default-Verhalten bzgl. copy/move.

Wäre nicht ein std::vector<element_t> die bessere Wahl? Dann bekommt man 
alle (copy/move, constructor/operator=/destructor) speziellen 
Member-Funktionen gratis. Man muss sich die Anzahl der Elemente nicht 
selbst merken und falls benötigt, ist das Ändern der Anzahl einfach 
möglich. Außerdem kann man mit std::unique_ptr<element_t[]> kein 
ranged-for benutzen. Und ...

Autor: Wilhelm M. (wimalopaan)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Rolf M. schrieb:
> Wilhelm M. schrieb:
>> In modernem Cpp kein expl. new/delete mehr. In diesem Fall wäre der
>> std::unique_ptr das richtige. Dann hat man auch das richtige
>> default-Verhalten bzgl. copy/move.
>
> Gibt es den denn auf dem AVR?

Für den AVR gibt es keine stdlibcpp, klar. Ist doch aber ne gute 
Fingerübung ;-)

Autor: Wilhelm M. (wimalopaan)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
mh schrieb:
> Wilhelm M. schrieb:
>> In diesem Fall wäre der
>> std::unique_ptr das richtige. Dann hat man auch das richtige
>> default-Verhalten bzgl. copy/move.
>
> Wäre nicht ein std::vector<element_t> die bessere Wahl? Dann bekommt man
> alle (copy/move, constructor/operator=/destructor) speziellen
> Member-Funktionen gratis. Man muss sich die Anzahl der Elemente nicht
> selbst merken und falls benötigt, ist das Ändern der Anzahl einfach
> möglich. Außerdem kann man mit std::unique_ptr<element_t[]> kein
> ranged-for benutzen. Und ...

Das kommt ganz darauf an ... Wenn es tatsächlich ne Queue werden soll, 
würde man den Container wohl eher generisch halten, sprich er schreibt 
sich ein Adapter-Template ...

... und verlagert das Probelm in den std::vector, den er sich für den 
avr-g++ auch selbst schreiben muss ...

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.