Konstruktor Argumente
-
Ömm, vielleicht habe ich dich jetzt falsch verstanden. Also wenn du das Argument in Memberfunktionen will, dann speichere das Argument als Instanzvariable.
-
Hi, ihr beiden,
hm...joa,ungefähr. Ich meinte sowas hier:
class foo { public: foo(const int _bufferSize) { } private: void tu_was() { int array[_bufferSize]; } };**
Status:**
Im Moment ist es so, dass die Funktion tu_was() die Variable _bufferSize nicht kennt.Was will ich machen?
Ich möchte ein Objekt einmal instanziieren und dabei dem Objekt die Puffergröße bekannt machen. Mit dieser Info soll dann die Memberfunktion tu_was arbeiten.
Bisher hatte ich das so, dass ich jedes Mal beim Funktionsaufruf diese Information übergeben habe. Aber das ist redundant, da sich die Puffergröße nach Objektinstanzierung nicht mehr ändert. Daher war meine Überlegung, das geschickterweise dem Konstruktor zu übergeben.Danke für eure Hilfe!
-
Achso. Ein Array auf dem Stack wirst du so aber nicht anlegen können, denn dafür brauchst du eine compile time Konstante. Abhilfe würde z.B. ein std::vector schaffen:
class foo { public: foo(int buffer_size) : buffer_size(buffer_size) { } private: size_t const buffer_size; void tu_was() { vector<int> array(buffer_size); } };PS: Namen, die mit einem Unterstrich anfangen, sind dem Compiler reserviert. Davon solltest du also die Finger lassen.
-
Aber jetzt habe ich doch buffer_size doppelt? Einmal im Konstruktor als Argument, und dann hab ich das mir selbst nochmal kopiert in `size_t const buffer_size.
OT:`
- Was spricht gegen:
int array[buffer_size];? - Was ist denn nun
size_t const name??
- Was spricht gegen:
-
Spoogy schrieb:
Aber jetzt habe ich doch buffer_size doppelt? Einmal im Konstruktor als Argument, und dann hab ich das mir selbst nochmal kopiert in [c]size_t const buffer_size.
Argumente sind temporär. Beim Aufruf werden die auf den Stack geschoben und nach verlassen der Funktion wieder runter. Wenn Du die Information später noch haben möchtest, musst du sie irgendwo speichern.
Wenn Du für die Klasse verschiedene Compilezeit Konstanten benutzt, kannst Du auch ein Template (wie z.B. [c]std::array<..>[/c]) machen.template<int Size> class foo { int buf[Size]; };Wenn der Wert erst zur Laufzeit bekannt ist, musst du ihn nunmal irgendwo für die Lebensdauer der foo Instanz speichern, am sinnvollsten in einer Membervariable. Wenn der Wert für alle Instanzen gilt, kannst du diese auch
staticdeklarieren.
-
Spoogy schrieb:
- Was spricht gegen:
int array[buffer_size];?
Illegal (außer buffer_size ist eine zur Compile-Zeit bekannte Konstante)
Spoogy schrieb:
- Was ist denn nun
size_t const name??
Ein Datenelement, welches im Konstruktor per Initialisierungsliste gesetzt werden muss und später nicht mehr verändert werden kann. Es ist vom Typ size_t, was ein vorzeichenloser Ganzzahltyp ist, der groß genug ist, die Anzahl der Bytes des größten zusammenhängenden Blocks im Speicher zu speichern.
Das ist wahrscheinlich auch nicht Deine letzte Frage zu C++. Daher würde ich Dir raten, ein schlaues C++ Buch zu besorgen, in dem Du die Grundlagen einfach nachlesen kannst. Das ist viel besser (für alle Beteiligten), als Dir von Forenmitgliedern C++ beibringen zu lassen.
- Was spricht gegen:
-
Vielen Dank
brotbernd schrieb:
Argumente sind temporär. Beim Aufruf werden die auf den Stack geschoben und nach verlassen der Funktion wieder runter. Wenn Du die Information später noch haben möchtest, musst du sie irgendwo speichern.
Ja, ich dachte fälschlicherweise, der Konstruktor stelle eine Ausnahme dar und behandelt Argumente wie Membervariablen anstatt wie lokale Variablen. Aber das ist Käse.
krümelkacker schrieb:
Spoogy schrieb:
- Was spricht gegen:
int array[buffer_size];?
Illegal (außer buffer_size ist eine zur Compile-Zeit bekannte Konstante)
Ach ja, klar!
Ich habe es jetzt mit einem Pointer gelöst, da dieser zur Laufzeit Speicher dynamisch zugewiesen bekommen kann:
int* MyArray = new int [buffer_size];Jetzt habe ich eine Frage zum
delete[]-Befehl:
Das erste Element meines Arrays habe ich mitMyArray[0] = 999;auf den Wert 999 initialisiert.
Nun habe ich meinen Pointer mit*++MyArray = 123;auf die nächste Speicheradresse (seines Types) inkrementiert und den Inhalt an dieser Stelle auf den Wert 123 gesetzt.
Leider kann ich jetzt den Speicher mitdelete [] MyArraynicht freigeben.
Ich erhalte:Debug Assertion Failed! (...) Expression: _BLOCK_TYPE_IS_VALID(pHead->nBlockUse)
Das gleiche geschieht auch dann, wenn ich nur den Pointer inkrementiere ohne einen Wert in die Adresse zu speichern (also nur ++MyArray)
Warum ist das so?
- Was spricht gegen:
-
Spoogy schrieb:
Ich habe es jetzt mit einem Pointer gelöst, da dieser zur Laufzeit Speicher dynamisch zugewiesen bekommen kann:
int* MyArray = new int [buffer_size];Darf ich fragen, warum du kein std::vector nehmen willst? Da musst du dich weder um die Allokation noch Freigabe kümmern? (Zumal er sich besser in C++ einfügt als ein C-Array).
Wenn du mit dem vector arbeitest sparst du dir unter anderem die Notwendigkeit einen eigenen Kopierkonstruktor und Zuweisungsoperator schreiben zu müssen, was du bei Zeigern tun musst - zumal du bei der Zeigerarithmetik wohl einige Probleme hast...
-
Der Zeiger auf den du delete[] aufrufst muss auf den Anfang eines durch new allokierten Block zeigen. Vor deinen eigentlichen Daten befinden sich dort z.B. Informationen, wie groß dieser Block ist. Diese Information braucht delete[] natürlich, um zu wissen wieviel gelöscht werden muss.
Benutze statt dem Array lieber einen std::vector<int>, dann musst du dir um solche sachen keine Gedanken machen.
-
brotbernd schrieb:
Der Zeiger auf den du delete[] aufrufst muss auf den Anfang eines durch new allokierten Block zeigen. Vor deinen eigentlichen Daten befinden sich dort z.B. Informationen, wie groß dieser Block ist. Diese Information braucht delete[] natürlich, um zu wissen wieviel gelöscht werden muss.
Danke, das wollte wissen.
D.h., man müsste vor dem Freigeben den Zeiger wieder auf seine ursprüngliche Adresse setzen.asc schrieb:
Darf ich fragen, warum du kein std::vector nehmen willst? Da musst du dich weder um die Allokation noch Freigabe kümmern? (Zumal er sich besser in C++ einfügt als ein C-Array).
Aus Performancegründen. Baue eine Echtzeitanwendung im Bereich der Audiosignalverarbeitung in Form eines VST-Plug-Ins.
Aber wenn std::vector keine Geschwindigkeitseinbußen mit sich bring werd ich das mir gerne anschauen. Ich wollte nur meine Theorie wieder auffrischen. Daher meine Fragen.asc schrieb:
(...)zumal du bei der Zeigerarithmetik wohl einige Probleme hast...
Welche denn genau?
-
Spoogy schrieb:
asc schrieb:
Darf ich fragen, warum du kein std::vector nehmen willst? Da musst du dich weder um die Allokation noch Freigabe kümmern? (Zumal er sich besser in C++ einfügt als ein C-Array).
Aus Performancegründen.
Solange du den vector richtig initialisierst (z.B. durch ein reserve-Aufruf wenn du mit push_back, oder dich eines entsprechenden Konstruktoraufrufes bedienst [z.B. einen mir der Anzahl und dem Standardwert] für einen direkten Indexzugriff), ist der std::vector von der Geschwindigkeit her ziemlich identisch mit einem dynamisch allozierten Array (sofern der Hersteller der STL nicht geschlammt hat).
Spoogy schrieb:
asc schrieb:
(...)zumal du bei der Zeigerarithmetik wohl einige Probleme hast...
Welche denn genau?
Unter anderem im Bezug mit delete. Zumal ich niemals den Ausgangszeiger direkt manipulieren würde (Da du diesen ggf. mehrmals braucht). Und wenn du schon über Indexzugriff arbeitest, warum überhaupt noch iterieren?
Zudem hoffe ich dennoch das du dir auch die von mir erwähnten Probleme im Bezug mit Zeigern & Klassen anschaust (Du musst entweder den Kopierkonstrzuktor und Zuweisungsoperator unterbinden, in dem du diese im private-Bereich deklarierst, aber niemals definierst, oder sie händisch schreiben; der std::vector wiederum kopiert sich selbstständig).