Ich versuche mich an einer Container-Klasse
-
[Nichtskapierer Mode="On"]
Ich hab mal ne Frage dazu:
Warum schreibst duthis->size = size;
Das dürfte doch eigentlich garnicht gehen, oder versteh ich das falsch,
size müsste doch automatisch als das size-Element der KLasse gewertet werden, oder? Wenn das stimmt müsste size seinem eigenem Wert zugewiesen werden, das wäre Zeitverschwendung. Außerdem hättest du dann eine undefinierte größe für das Array.
[Nichtskapierer Mode="Off"]thx
Glamdring
-
Hi,
nein, das zweite size bezieht sich auf die lokale Veriable.
ChrisM
PS: Warum der Standardkonstruktor wohl Standardkonstruktor heißt? Richtig, weil er immer dann aufgerufen wird, wenn kein anderer spezifiert wird!
-
@Glamdrink
size ist in diesem Kontext der Parameter des Konstruktors. this->size ist eine Instanzvariable der Klasse Array.
Wegen solcherlei Namenskonflikte neigen 86.72% aller C++ Programmierer dazu, gewisse Namenskonventionen einzuhalten, die z.B. Member- und Parameternamen unterscheiden.
-
template <class T> Array<T>::Array(int size) { data = new T[size]; this->size = size; for (int i = 0; i < size; ++i) data[i] = T(); }
So besser? Mir ist schon klar, dass der StandardCtor immer aufgerufen wird. Aber ich will ja auch primitive Typen nicht uninitialisiert haben.
SecureZeroMemory ist mehr oder weniger eine Lüge. Ich verstehe die Beschreibung so, dass SecureZeroMemory in keinem Fall wegoptimiert wird, während ZeroMemory vom Compiler wegoptimiert werden kann (wann und wozu, wer weiß es).
-
Optimizer schrieb:
So besser? Mir ist schon klar, dass der StandardCtor immer aufgerufen wird.
Nein.
du holst dir rohen speicher und initialisierst alle benötigten elemente mittels placement new - dadurch hast du keine standard ctor calls mehr.new T[size];
legt size Elemente vom Typ T an, und initialisiert sie mittels standard ctor.und deine schleife ruft zusätzlich noch schön den operator= und standard ctor pro element auf.
das macht:
2size StdCtor calls
1size op=n bisschen viel, oder?
-
Aber wenn ich die Schleife nicht mache, bleiben primitive Typen uninitialisiert. Das will ich unbedingt vermeiden.
-
verwende operator new (size_t) oder einen allokator und dann algorithmen wie uninitialized_fill, um dir mal einen anhaltspunkt zu geben.
-
Andere Frage (hat nichts mit dem davor zu tun):
Kann ich von std::vector ableiten, um den operator[] zu redefinieren?template<class _Ty, class _Ax = allocator<_Ty> > class Array : public std::vector<class _Ty, class _Ax = allocator<_Ty> > { };
Offensichtlich stört sich der Compiler an der zweiten Template-Argumentenliste. Aber ohne Argumentenliste nach std::vector geht es auch nicht.
-
Hallo,
std::vector ist nicht als öffentliche Basisklasse gedacht.template<class _Ty, class _Ax = allocator<_Ty> > class Array : public std::vector<class _Ty, class _Ax = allocator<_Ty> > { };
Das ist syntaktischer Käse. So wäre's richtig:
#include <vector> template<class _Ty, class _Ax = std::allocator<_Ty> > class Array : public std::vector<_Ty, _Ax> { };
Aber noch einmal, nur für den Fall, dass das Kurzzeitgedächtnis bereits geleert wurde, std::vector ist nicht als öffentliche Basisklasse gedacht und auch nicht als solche geeignet.
-
template<class _Ty, class _Ax = allocator<_Ty> > class Array : public std::vector<_Ty,_Ax> //Du willst ja von einem konkreten Vektor erben (geht ja nicht anders) { };
Namen, die mit Unterstrich beginnen, sind reserviert. Lieber nicht verwenden.
-
HumeSikkins schrieb:
Aber noch einmal, nur für den Fall, dass das Kurzzeitgedächtnis bereits geleert wurde, std::vector ist nicht als öffentliche Basisklasse gedacht und auch nicht als solche geeignet.
Was ist daran schlecht, bzw. (weil ich dir das jetzt einfach mal glaube) welche anderen Möglichkeiten habe ich, um den operator[] zu redefinieren?
Ich will, dass er Indexsicher ist.EDIT: Die abgeleitete Klasse scheint auch nicht zu funktionieren:
Array<int> blubb(10);
error C2664: 'Array<_Ty>::Array(const Array<_Ty> &)': Konvertierung des Parameters 1 von 'int' in 'const Array<_Ty> &' nicht möglich
with
[
_Ty=int
]
and
[
_Ty=int
]
Ursache: Konvertierung von 'int' in 'const Array<_Ty>' nicht möglich
with
[
_Ty=int
]
-
Optimizer schrieb:
HumeSikkins schrieb:
Aber noch einmal, nur für den Fall, dass das Kurzzeitgedächtnis bereits geleert wurde, std::vector ist nicht als öffentliche Basisklasse gedacht und auch nicht als solche geeignet.
Was ist daran schlecht, bzw. (weil ich dir das jetzt einfach mal glaube) welche anderen Möglichkeiten habe ich, um den operator[] zu redefinieren?
std::vector ist keine gute öffentliche Basisklasse, da vector keine virtuellen Methoden und insbesondere keinen virtuellen Destruktor besizt. Es ist also zum einen nicht sinnvoll möglich ein abgeleitetes Objekt über eine Basisklassenreferenz anzusprechen (der eigentliche Grund für öffentliche Vererbung) und zum anderen kannst du sogar undefiniertes Verhalten heraufbeschwören, nämlich genau dann, wenn du ein dynamisch erzeugtes Objekt über eine Basisklassenreferenz löschst.
Leitest du öffentliche von std::vector ab, so missbrauchst du die öffentliche Vererbung als Mittel zur simplen Codewiederverwendung (des Codes der Basisklasse). Und das ist eine Sache die man tunlichst vermeiden sollte.
Die einzige saubere Möglichkeit ist Containment.
template <class T> class Array { private: std::vector<int> impl_; public: // Interface das du brauchst forwarded zu impl_ };
Für schreibfaule (keine gute Motivation) mag auch private-Vererbung noch ok sein.
-
Hei, noch nie probiert mit privater Vererbung zu verhindern das ein Objekt auf einen Basiszeiger landen kann.
Wenn das im Standard definiert ist (nehme ich an , sonst würdest es nich schreiben...
)) => thx
-
Knuddlbaer schrieb:
Hei, noch nie probiert mit privater Vererbung zu verhindern das ein Objekt auf einen Basiszeiger landen kann.
Wenn das im Standard definiert ist (nehme ich an , sonst würdest es nich schreiben...
)) => thx
du kannst trotzdem (über umweg) einen zeiger auf die basisklasse bekommen. aber als nicht-friend-nicht-klassenmember eigentlich keine gefahr
-
Für schreibfaule (keine gute Motivation) mag auch private-Vererbung noch ok sein.
Warum? Was ist denn an private-Vererbung schlechter als an einer Membervariable?
Kommt das nicht aufs Gleiche raus?
-
Optimizer schrieb:
welche anderen Möglichkeiten habe ich, um den operator[] zu redefinieren?
Einfach ein assert() im operator[] einfügen?
Es ist ja nicht verboten die Library zu ändern.IMHO ist dies die beste Lösung - denn von value Typen zu erben bringt oft mehr Probleme als Vorteile.
-
Wie denn ? Mein Compiler sagt mir bei bisherigen Versuchen das eine Umwandlung zwar vorhanden ist, aber nicht darauf zugegriffen werden kann.
@Shade
Ändern an der Lib ist nicht verboten aber unsinnig. Es wäre nicht mehr portabel.
-
Knuddlbaer schrieb:
Ändern an der Lib ist nicht verboten aber unsinnig. Es wäre nicht mehr portabel.
Wieso? es geht nicht um Funktionalität sondern um ein assert.
Da bleibt alles portabelDenn wenn das assert fehlt, ändert sich das Programmverhalten nicht sonderlich.
-
Knuddlbaer schrieb:
@davi
Wie denn ? Mein Compiler sagt mir bei bisherigen Versuchen das eine Umwandlung zwar vorhanden ist, aber nicht darauf zugegriffen werden kann.class private_base { public: void foo () { cout << "foo\n"; } }; class derived : private_base { friend int main(); }; int main () { derived d; d.foo(); }
-
Ahja, thx