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


von Wolfgang K. (Firma: Neutron Mikroelektronik GmbH) (wollekette)


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.
1
typedef struct
2
{
3
    int a;
4
    int b;
5
} element_t;
6
7
class ElementsQueue 
8
{
9
    element_t items[42];
10
};

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?

von Felix U. (ubfx)


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.
1
class ElementsQueue 
2
{
3
    element_t *items;
4
5
    ElementsQueue(unsigned n)
6
    {
7
        items = new element_t[n];
8
    }
9
};

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
von Oliver S. (oliverso)


Lesenswert?

Die dann auftretenden Fehlermeldungen löst dieser Beitrag:

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

Oliver

von Markus F. (mfro)


Lesenswert?

möglicherweise ein potentieller Kandidat für ein Klassen-Template:
1
template <size_t size> struct element_queue
2
{
3
    struct element & operator [](int index) { return items[index]; };
4
5
    struct element items[size];
6
};
7
8
...
9
10
    struct element_queue<10> elements;
11
12
    elements[7].a = 4711;
13
...

von Wolfgang K. (Firma: Neutron Mikroelektronik GmbH) (wollekette)


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.

von Scott Meyers (Gast)


Lesenswert?

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

von Felix U. (ubfx)


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.

von Wolfgang K. (Firma: Neutron Mikroelektronik GmbH) (wollekette)


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 ;-)

von Scott Meyers (Gast)


Lesenswert?

Du schreibst C++-Code und willst malloc()/free() verwenden????

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

von Rolf M. (rmagnus)


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.

von Rufus Τ. F. (rufus) Benutzerseite


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.

von M.K. B. (mkbit)


Lesenswert?

Ich würde den Beitrag von Felix U. noch ergänzen:
1
class ElementsQueue
2
{
3
    element_t *items;
4
5
    ElementsQueue(unsigned n)
6
    {
7
        items = new element_t[n];
8
    }
9
10
    ~ElementsQueue()
11
    {
12
        // wichtig, damit der Speicher auch wieder freigegeben wird
13
        delete[] items;
14
    }
15
};

von Rolf M. (rmagnus)


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.

von Wilhelm M. (wimalopaan)


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.

von Rolf M. (rmagnus)


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?

von mh (Gast)


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 ...

von Wilhelm M. (wimalopaan)


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 ;-)

von Wilhelm M. (wimalopaan)


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 ...

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.