Kopierkonstruktor ohne Speicher freigeben?
-
Ah, ok. Habs verstanden. Danke dir

-
Ramanujan schrieb:
SeppJ schrieb:
new[] ist niemals eine bessere Alternative zu vector oder string.
Wirklich niemals? Ich könnte mir Fälle vorstellen, in denen man sehr viele sehr kleine Arrays dynamischer, implizit gegebener Größe benötigt, bei denen der Overhead von vector zu viel Speicher verbrauchen würde. Von daher würde ich sagen, dass new[] fast nie eine bessere Alternative zu vector ist.
Welchen Overhead gegenüber new[] hat std::vector denn?
-
manni66 schrieb:
Ramanujan schrieb:
SeppJ schrieb:
new[] ist niemals eine bessere Alternative zu vector oder string.
Wirklich niemals? Ich könnte mir Fälle vorstellen, in denen man sehr viele sehr kleine Arrays dynamischer, implizit gegebener Größe benötigt, bei denen der Overhead von vector zu viel Speicher verbrauchen würde. Von daher würde ich sagen, dass new[] fast nie eine bessere Alternative zu vector ist.
Welchen Overhead gegenüber new[] hat std::vector denn?
Praktisch hat vector in der Regel die Größe von 3 Pointern, wohingegen bei new ein Pointer und eine Größenangabe (~eine weitere Pointergröße) reicht, sofern man nicht vor hat, das Array zu vergrößern.
Das Beispiel ist derart konstruiert, dass ich bei nie bleibe. Wenn wir wirklich immer alle möglichen Ausnahmen berücksichtigen, dann kann man in diesem Forum gar nichts mehr sagen, ohne immer ein "fast" in die Aussage aufzunehmen.
-
SeppJ schrieb:
Wenn wir wirklich immer alle möglichen Ausnahmen berücksichtigen, dann kann man in diesem Forum gar nichts mehr sagen, ohne immer ein "fast" in die Aussage aufzunehmen.
Man sollte auch fast nie nie schreiben, sondern fast immer fast nie

-
Bitte tötet mich nicht bei meinen ganzen blöden Fragen ...
Ich versuche gerade eine Klasse in eine andere Klasse einzukapseln. Das problem ist nur, dass die Klasse CEthernet umbedingt Parameter für den Konstruktor braucht. Momentan habe ich dies mit einem Pointer gelöst. Kann man das auch ohne Pointer lösen oder muss das so sein? Ist das in diesem Fall in Ordnung oder sollte man da lieber eine extra Methode zum Einlesen schreiben? (Ich meine soetwas ähnliches schonmal bei QT gesehen zu haben)
class CPacket { public: //Methoden CPacket(const struct pcap_pkthdr *pkt_header, const u_char *pkt_data); ~CPacket(void); //Elemente CEthernet *eth; private: }; class CEthernet { public: //Methoden CEthernet(const struct pcap_pkthdr *pkt_header, const u_char *pkt_data); ~CEthernet(void); //Elemente u_char dstmac[6], srcmac[6]; short frametype; }; ... CPacket::CPacket(const struct pcap_pkthdr *pkt_header, const u_char *pkt_data) { //======================================================> //Ethernet-Schicht einlesen (14 Bytes) eth = new CEthernet(pkt_header, pkt_data); //unschön? } CPacket::~CPacket(void) { delete eth; }
-
C-Präfixe kotzen mich an.
-
Telefonmann schrieb:
Ich versuche gerade eine Klasse in eine andere Klasse einzukapseln. Das problem ist nur, dass die Klasse CEthernet umbedingt Parameter für den Konstruktor braucht.
Initialisierungsliste
-
Kellerautomat schrieb:
C-Präfixe kotzen mich an.
KPacket, KEthernet- besser?
-
hustbaer schrieb:
Kellerautomat schrieb:
C-Präfixe kotzen mich an.
KPacket, KEthernet- besser?

Btw: Was hab ich mir eigentlich unter einem "Ethernet"-Objekt vorzustellen?
-
SeppJ schrieb:
manni66 schrieb:
Ramanujan schrieb:
SeppJ schrieb:
new[] ist niemals eine bessere Alternative zu vector oder string.
Wirklich niemals? Ich könnte mir Fälle vorstellen, in denen man sehr viele sehr kleine Arrays dynamischer, implizit gegebener Größe benötigt, bei denen der Overhead von vector zu viel Speicher verbrauchen würde. Von daher würde ich sagen, dass new[] fast nie eine bessere Alternative zu vector ist.
Welchen Overhead gegenüber new[] hat std::vector denn?
Praktisch hat vector in der Regel die Größe von 3 Pointern, wohingegen bei new ein Pointer und eine Größenangabe (~eine weitere Pointergröße) reicht, sofern man nicht vor hat, das Array zu vergrößern.
Das Beispiel ist derart konstruiert, dass ich bei nie bleibe. Wenn wir wirklich immer alle möglichen Ausnahmen berücksichtigen, dann kann man in diesem Forum gar nichts mehr sagen, ohne immer ein "fast" in die Aussage aufzunehmen.
Warum verbraucht ein vector die größe von 3 pointern? Also das ist schon richtig. Aber eigentlich müsste doch ein Pointer für das Datenfeld und eine Größenangabe reichen oder?
Beim Array in meinem Beispiel wird zusätzlich nur 1 pointer verbraucht, da die Größe ja implizit gegeben ist (d.h. z.B. durch eine Funktion, die einen Index auf die Größe abbildet).
Aber ich stimme dir voll zu, dass das Beispiel schon sehr konstruiert ist. Und man kann natürlich auch hierbei speichereffizient mit vector arbeiten, indem man einen vector nimmt, in dem alle kleinen Arrays hintereinander gespeichert sind und ein zweiten vector, der die Pointer beinhaltet. Durch die Differenz zweier aufeinanderfolgender Pointer hätte man dann auch Größe quasi explizit gegeben. Wenn man allerdings die Größe eines Arrays in der Mitte ändern möchte, kann man diese Konstruktion schon wieder in die Tonne kloppen...
-
Ramanujan schrieb:
Warum verbraucht ein vector die größe von 3 pointern? Also das ist schon richtig. Aber eigentlich müsste doch ein Pointer für das Datenfeld und eine Größenangabe reichen oder?
Eben aus diesem Grund programmiert man sich seine Container auch nicht selber, sondern überlässt das denen, die sich damit auskennen. Nur ein Zeiger auf Anfang und eine Größenangabe wären ganz furchtbar ineffizient beim Vergrößern des vectors (also bei einer häufigsten Operationen überhaupt). Es wäre mWn nicht einmal möglich, damit die gemittelt konstante Laufzeitanforderung für ein push_back zu erfüllen, sondern ein push_back wäre mindestens linear im Zeitaufwand. Üblich sind daher: Zeiger auf Anfang, Zeiger auf Ende der Daten, Zeiger auf Ende des reservierten Bereichs.
-
Ja, stimmt, ich hatte in dem Moment vergessen, dass die Größe des reservierten Feldes mitgespeichert werden muss.
-
Es war einmal ein Programm, das rechnete viel mit 3D Vektoren. Vektoren aus jeweils drei
floats.std::vector<float>Vektoren aus jeweils dreifloats
Es wurde dann umgeschrieben, dann war es schneller und brauchte weniger Speicher, und alle waren froh. (Später wurde es dann eingestampft und komplett neu entwickelt, weil es immer noch grässlich war, aber das ist eine andere Geschichte und soll ein andermal erzählt werden)Das ist nicht konstruiert und nicht gelogen.
(Dafür passt es nicht wirklich zu dem was hier eigentlich diskutiert wird, aber hey, man kann nicht alles haben :D)(ps. das Programm war nicht von mir, ich durfte es nur bewundern!)
-
Kellerautomat schrieb:
Btw: Was hab ich mir eigentlich unter einem "Ethernet"-Objekt vorzustellen?
Vermutlich etwas was lieber eine struct werden wollte, und die Daten speichert die in der Ethernet-Header so drinstehen (bzw. wenigstens ein paar davon).
-
Telefonmann schrieb:
Bitte tötet mich nicht bei meinen ganzen blöden Fragen ...
Oh ... ich versuch's mal ...
Telefonmann schrieb:
Ich versuche gerade eine Klasse in eine andere Klasse einzukapseln. Das problem ist nur, dass die Klasse CEthernet umbedingt Parameter für den Konstruktor braucht. Momentan habe ich dies mit einem Pointer gelöst. Kann man das auch ohne Pointer lösen oder muss das so sein?
Das kann man auch ohne Pointer lösen. Das Stichwort fiel ja auch schon: Initialisierungsliste. Bitte besorg dir ein gescheites C++ Grundlagenbuch. Es wird allen Ärger ersparen, dir und uns.
Telefonmann schrieb:
Ist das in diesem Fall in Ordnung
Meinst du mit "das" die Verwendung eines rohen Zeigers? Nee, nicht wirklich.
Telefonmann schrieb:
class CPacket { public: //Methoden CPacket(const struct pcap_pkthdr *pkt_header, const u_char *pkt_data); ~CPacket(void); //Elemente CEthernet *eth; private: }; class CEthernet { public: //Methoden CEthernet(const struct pcap_pkthdr *pkt_header, const u_char *pkt_data); ~CEthernet(void); //Elemente u_char dstmac[6], srcmac[6]; short frametype; }; ... CPacket::CPacket(const struct pcap_pkthdr *pkt_header, const u_char *pkt_data) { //======================================================> //Ethernet-Schicht einlesen (14 Bytes) eth = new CEthernet(pkt_header, pkt_data); //unschön? } CPacket::~CPacket(void) { delete eth; }Mir ist schleierhaft, warum du in CEthernet einen Destruktor deklarierst. Außerdem verletzt du bei CPacket die Dreierregel. Besorg dir bitte ein schlaues C++ Buch.