std::vector mit unterschiedliche grossen Datentypen
-
@titan99_ Verstehst du den Unterschied zwischen einem Objekt und einem Zeiger auf das Objekt?
-
@hustbaer Ja einigermassen. Also Objekte/Variablen haben eine Adresse und die Daten. Bei zusammenhängendem Speicher sind die Adressen zusammenhängend. Es wird glaube ich jeweils ein Byte adressiert, aber genau weiss ich es nicht.
Edit: Also wenn ich die Zeiger oder die Adressen im vector speichere, sind nur die Variablen wo die Adressen gespeichert sind im Speicher zusammenhängend.
-
@titan99_ sagte in std::vector mit unterschiedliche grossen Datentypen:
Edit: Also wenn ich die Zeiger oder die Adressen im vector speichere, sind nur die Variablen wo die Adressen gespeichert sind im Speicher zusammenhängend.
Bingo.
-
Beachte auch:
struct Foo { virtual void p() { cout << "Foo.\n"; } }; struct Bar : public Foo { void p() override { cout << "Bar.\n"; } }; Bar b; Foo f = b; f.p(); // Foo. //Aber: Bar *pb = new Bar; Foo *pf = pb; pf->p(); //Bar.
(Natürlich sonst auch an virtual ~Foo denken und Smartptr verwenden)
-
weiss nicht ob das sinnvoll ist, aber wenn man will dass alle objekte gleich groß sind, dann könnte man sie in eine union stecken. dabei gibt das größte objekt die größe vor.
-
@Bushmaster sagte in std::vector mit unterschiedliche grossen Datentypen:
weiss nicht ob das sinnvoll ist,
Nein. std::variant.
-
@titan99_ sagte in std::vector mit unterschiedliche grossen Datentypen:
Also im Moment frage ich mich, für was es dann upcasting und downcasting gibt. Also ich bin am überlegen, einen std::vector mit smart_pointern zu verwenden, oder können dann auch Daten verloren gehen?
Mit Smart Pointern kannst du das Problem umgehen.
-
@manni66 sagte in std::vector mit unterschiedliche grossen Datentypen:
@Bushmaster sagte in std::vector mit unterschiedliche grossen Datentypen:
weiss nicht ob das sinnvoll ist,
Nein. std::variant.
die idee hatte schon jemand; https://en.cppreference.com/w/cpp/utility/variant
The class template std::variant represents a type-safe union.
wurde aber erst 2017 umgesetzt.
-
@eigenartig sagte in std::vector mit unterschiedliche grossen Datentypen:
Mit Smart Pointern kannst du das Problem umgehen.
Quatsch. Das hat nix mit smarten Pointern zu tun sondern mit Laufzeitpolymorphie. Und das geht eben definitionsgemäß nur wenn man Referenzen (Pointer oder Referenzen) auf die verschiedenen Objekte hat. Man darf diese Pointer dann unter gewissen umstänten casten.
-
@manni66 sagte in std::vector mit unterschiedliche grossen Datentypen:
@Bushmaster sagte in std::vector mit unterschiedliche grossen Datentypen:
weiss nicht ob das sinnvoll ist,
Nein. std::variant.
variant ist cool. visual studio kennt es, nachdem c++17 in den compiler settings aktiviert wurde.
int main() { variant<int, double, char, long, string, char*> v; cout << sizeof(v) << endl; // 40 bytes wtf? v = 1234; auto val = get_if<int>(&v); cout << typeid(*val).name() << ": " << *val << endl;; v = 1234.5678; auto val2 = get_if<double>(&v); cout << typeid(*val2).name() << ": " << *val2 << endl;; }
bisschen viel overhead, aber das liegt wohl daran weil ich für debug compiliert habe.
-
Eher wegen dem string und SSO.
-
@Mechanics sagte in std::vector mit unterschiedliche grossen Datentypen:
Eher wegen dem string und SSO.
aber ich tue keinen string rein. die typenliste gibt doch nur an, was hinein darf.
-
@Bushmaster Und string mit SSO ist das größte was hinein kann und damit ist ein variant auch mindesten so groß. (und die Größe steht natürlich schon zur compiletime fest.)
-
@Swordfish sagte in std::vector mit unterschiedliche grossen Datentypen:
@Bushmaster Und string mit SSO ist das größte was hinein kann und damit ist ein variant auch mindesten so groß. (und die Größe steht natürlich schon zur compiletime fest.)
du kannst recht haben. im realease-modus sind es 32 bytes, also nur 8 bytes weniger.
-
Dieser Beitrag wurde gelöscht!
-
@wob sagte in std::vector mit unterschiedliche grossen Datentypen:
Natürlich sonst auch an virtual ~Foo denken
virtual dtor in der Basisklasse spielt aber nur eine Rolle, wenn abgeleitete Klassen einen Desktruktor implementiert haben, damit auch der Destruktor in der abgeleiteten Klasse aufgerufen wird? siehe stackoverflow.
Oder sollten Klassen, die einen dtor implementiert haben und von denen abgeleitet wird, immer virtual dtor haben?
-
@titan99_ sagte in std::vector mit unterschiedliche grossen Datentypen:
Oder sollten Klassen, die einen dtor implementiert haben und von denen abgeleitet wird, immer virtual dtor haben?
Ja, sonst wird beim Löschen über den Basiszeiger nicht korrekt freigegeben bzw. nicht korrekt die Destruktoren der Member aufgerufen.
-
@titan99_ sagte in std::vector mit unterschiedliche grossen Datentypen:
Oder sollten Klassen, die einen dtor implementiert haben und von denen abgeleitet wird, immer virtual dtor haben?
Wenn die Objekte über Basisklassenzeiger gelöscht werden können, dann wäre es gut wenn der Dtor der Basisklasse virtual ist. Denn ob die abgeleitete Klasse einen Dtor hat oder nicht, das kann sich schnell mal ändern. Und der der das ändert, sieht nicht unbedingt ob der Dtor der Basisklasse virtual ist oder nicht.
-
@hustbaer sagte in std::vector mit unterschiedliche grossen Datentypen:
Denn ob die abgeleitete Klasse einen Dtor hat oder nicht, das kann sich schnell mal ändern. Und der der das ändert, sieht nicht unbedingt ob der Dtor der Basisklasse virtual ist oder nicht.
Das Problem ist nicht, ob die abgeleitete Klasse einen (explizit geschriebenen) Destruktor hat. Wenn der Konstruktor der Basisklasse nicht virtual ist, werden Destruktoren der Member nicht ausgeführt:
#include <iostream> struct Member { ~Member() { std::cout << "Ich geh kaputt\n"; } }; struct Base { ~Base(){} }; struct Derived : Base { Member member; }; int main() { Base *b = new Derived; delete b; }
gibt nichts aus.
-
@manni66 sagte in std::vector mit unterschiedliche grossen Datentypen:
werden Destruktoren der Member nicht ausgeführt:
Weil der Destructor von Derived nicht ausgeführt wird wenn ~Base nicht virtual ist.
Mann.