eigener klassentyp im vector
-
Z2 schrieb:
Du mußt dich schon einigen, ob du Objekte der Klasse a oder Zeiger auf Objekte der Klasse a in den Vector legen willst.
z.B. so:
a einA; meinAvector.push_back(einA);oder eben
std::vector<a*> meinAvector; meinAvector.push_back(new a);.. aber: Später das delete nicht vergessen "
Gruß,
Simon2.
-
Wobei noch darauf hinzuweisen ist, daß dieser Code so für sich nicht korrekt ist, weil die Exception-Sicherheit fehlt (irgendwie habe ich das Gefühl ich wiederhole mich in letzter Zeit ziemlich viel
).Entweder mußt du einen try-catch-Block um dieses Konstrukt legen (sehr unpraktisch) oder statt der nackten Zeiger einen geeigneten SmartPointer verwenden (z.B. boost::shared_ptr). Im zweiten Fall kannst du dir dann auch das delete sparen.
-
Und wie sieht deine Begründung für Exception Checking aus?
BTW ist es nicht grad üblich try & catch in Foren zu schreiben.
-
Z2 schrieb:
Wobei noch darauf hinzuweisen ist, daß dieser Code so für sich nicht korrekt ist, weil die Exception-Sicherheit fehlt
Das ist übrigens komplett falsch!
-
Michael E. schrieb:
Z2 schrieb:
Wobei noch darauf hinzuweisen ist, daß dieser Code so für sich nicht korrekt ist, weil die Exception-Sicherheit fehlt
Das ist übrigens komplett falsch!
kann man falsch steigern? Die Aussage ist falsch, da Exceptionsicherheit nicht notwendige Bedingung für Korrektheit ist. Andererseits ist das Konstrukt tatsächlich nicht exceptionsicher.
-
Michael E. schrieb:
Und wie sieht deine Begründung für Exception Checking aus?
Exceptionsicherheit?
-
camper schrieb:
Die Aussage ist falsch, da Exceptionsicherheit nicht notwendige Bedingung für Korrektheit ist.
Ist sie nicht? Exceptions sind Teil der Sprache (selbst elementare Konstrukte wie new können werfen). Man muß also davon ausgehen, daß Exceptions geworfen werden können.
Wenn eine Exception zwischen dem Code-Segment und dem Aufruf von delete geworfen und nicht rechtzeitig gefangen und abgehandelt wird, entsteht an dieser Stelle ein Memory-Leak. Ein Memory-Leak ist ein Bug und ein Programm, das einen Bug enthält, ist nicht korrekt.
-
Z2 schrieb:
Entweder mußt du einen try-catch-Block um dieses Konstrukt legen (sehr unpraktisch) oder statt der nackten Zeiger einen geeigneten SmartPointer verwenden (z.B. boost::shared_ptr). Im zweiten Fall kannst du dir dann auch das delete sparen.
nö, lieber ein vector-Typ der weiß was ein Pointer ist. In boost gibt es doch ptr-vector oder so ähnlich
-
Z2 schrieb:
selbst elementare Konstrukte wie new können werfen
können, nicht werden oder müssen. Wenn die Umgebungsparameter hinreichend bestimmt sind, kann man das aber möglicherweise ausschließen. Schließlich müssen wir Korrektheit nicht unbedingt generell abstrakt feststellen, sondern können uns auch mit einer konkreten Implementation und Umgebung zufrieden geben.
-
camper schrieb:
Z2 schrieb:
selbst elementare Konstrukte wie new können werfen
können, nicht werden oder müssen. Wenn die Umgebungsparameter hinreichend bestimmt sind, kann man das aber möglicherweise ausschließen. Schließlich müssen wir Korrektheit nicht unbedingt generell abstrakt feststellen, sondern können uns auch mit einer konkreten Implementation und Umgebung zufrieden geben.
push_back ist doch dann ein idealer Kandidat für eine Exception, da vielleicht Speicher allokiert werden muss...
-
rüdiger schrieb:
camper schrieb:
Z2 schrieb:
selbst elementare Konstrukte wie new können werfen
können, nicht werden oder müssen. Wenn die Umgebungsparameter hinreichend bestimmt sind, kann man das aber möglicherweise ausschließen. Schließlich müssen wir Korrektheit nicht unbedingt generell abstrakt feststellen, sondern können uns auch mit einer konkreten Implementation und Umgebung zufrieden geben.
push_back ist doch dann ein idealer Kandidat für eine Exception, da vielleicht Speicher allokiert werden muss...
richtig, aber vielleicht garantiert die umgebung ja, dass das nicht passiert.
-
hallo danke für die antworten,
mich interessiert sehr die erste antwort.
ich möchte in dem vector aber immer verschiedene objekte drin haben.der fall sieht so aus. klasse a und b waren nur pseudonamen. ich habe mehrere clienten die sich per socketprogrammierung an einem server anmelden. wenn der server den clienten dann akzeptiert soll der passende socket im vector gehaslten werden, so das der server über den vector mit allen clienten kommunizieren kann.
geht das dann so das dann so wie in der ersten antwort? kanns grade nicht ausprobieren weil ich das für einen nebenjob machen muss. und da bin ich erst morgen abend wieder.
wann muss ich das delete benutzen? dann wenn der client nicht mehr da ist? und wie verwende ich das delete richtig?
mfg
vielen dank
-
ein zusatz noch,
wenn ich ein objekt dem vektor hizufüge und die methode verlassen wird in dem das objekt deklariert wurde. ist es dann noch im vector? oder gibt es das objekt dann nicht mehr weil die methode verlassen wurde??
-
Der vector<> speichert eine Kopie des Objekts, also überlebt es dort drin das Ende deiner Methode.
Aber wenn es dir um Polymorphie geht, kommst du um einen vector<basis*> (bzw. boost::ptr_vector) wohl nicht herum. Das delete wird dann in dem Moment nötig, bevor du den letzten Zeiger auf das Objekt verlierst (um bei sowas den Überblick zu behalten, helfen Smart-Pointer weiter ;)).
-
Z2 schrieb:
...irgendwie habe ich das Gefühl ich wiederhole mich in letzter Zeit ziemlich viel...
Schau an, da sind wir schon 2.

Wer hat hier eigentlich nach exception safety gefragt ?
Poste mal Deinen Code, dann werde ich Dir zeigen, warum der nicht threadsafe ist.
Oder den threadsafen, der aber nicht performanceoptimiert ist.
Oder den performanceoptimierten, der aber schwer erweiterbar ist.
Oder den leicht erweiterbaren, der ....
Für all diese edlen Zielsetzungen bietet C++ Konstrukte an, um sie abzubilden - trotzdem gehören sie nicht automatisch zur "Korrektheit".Eine Kunst beim Programmieren ist, genau die Anforderung abzubilden.
... und bei einem simplen "einmal-durchlauf-Programm" auf einem modernen Betriebssystem, spricht nichts dagegen, nach einer Ausnahme den Speicher vom OS aufräumen zu lassen.
Ich habe den Eindruck, Du hast für Dich gerade entdeckt, dass exception-safety gerade gaaaanz sexy ist und verpulst das jetzt bei jeder Gelegenheit jedem, der es hören will ... und auch allen Anderen.

Auch hier nochmal: Möchtest Du einem Einsteiger exception-safety erklären (wogegen ich gar nichts habe), dann tue es auch ... aber dann auch gründlich Weiß der Kollege, was exceptions sind, wann man sie wirft, wie man sie fängt, wann stack-unwinding passiert, was exc.-spec. sind (und was nicht), welche Anforderungen man an exception-safety stellen kann (try catch allein reicht nicht !), .... ?
Wenn Du so viel Spaß an dem Thema hast: schreib' doch mal einen schönen Artikel dazu (vielleicht in die FAQ ?) und verweise einfach jeden Noob, der mit Zeigern arbeiten will darauf.
Gruß,
Simon2.
-
danke, aber was meinste mit polymorphy? sprichst du hier von mehrfachvererbung?
oder meinste das ich verschiedene Objekte haben will? wahrscheinlich das letztere,
ich habe c++Referenz das Buch und da guckt ich heute mal nach ob was über diesen Vector Typ steht, aber ich glaube mich zu errinern das da nichts steht , du meinst ich komme daran nicht herum, kannst mir mal das prinzip erklären wo der unterschied zu dem ist wie ich das gemacht habe? oder einen kleinen code zeigen der verschieden objekte in zb. einer for schleife in einem vector ablegt?in Java geht das ganz einfach, das ist da selbstverständlich mit dem new operator super easy, aber hier fehlt mir der zusammenhang ein bischen.
in java ungefähr so
for (int i=0;i<5;i++){ A a=new a(); vectorB.add(a); }ich glaub der befehl heisst add oder so naja aber so ungefähr funzt es.alle objekte sind verschieden.
will das selbe jetzt nur
für c++.mfg
-
newly schrieb:
danke, aber was meinste mit polymorphy? sprichst du hier von mehrfachvererbung?
oder meinste das ich verschiedene Objekte haben will? wahrscheinlich das letztere,Polymorphier bedeutet, daß erst zur Laufzeit der tatsächliche Typ feststeht (du also verschieden Typen gemeinsam verarbeiten kannst).
in Java geht das ganz einfach, das ist da selbstverständlich mit dem new operator super easy, aber hier fehlt mir der zusammenhang ein bischen.
In Java arbeitest du auch (fast) nur mit Pointern - und mußt dich nicht weiter darum kümmern, was hinter den Kulissen mit ihnen passiert (Stichwort: Garbage Collector). In C++ verwendet man Pointer erst, wenn man sie unbedingt braucht (und dann muß man genau darauf achten, wer wann den Pointer wieder freigeben darf).
In C++ sieht dein Code etwa so aus:
for(int i=0;i<5;++i) { A a;//ohne 'new' - das Objekt wird direkt auf dem Stack angelegt ... a mit Werten füllen vectorB.push_back(a); }(push_back() speichert eine Kopie des übergebenen Objekts, also brauchst du dich nicht darum kümmern, daß a am Ende des Schleifendurchlaufs entsorgt und in der nächsten Runde wiederverwendet wird)
-
Na, dann wollen wir mal:

camper schrieb:
rüdiger schrieb:
camper schrieb:
Z2 schrieb:
selbst elementare Konstrukte wie new können werfen
können, nicht werden oder müssen. Wenn die Umgebungsparameter hinreichend bestimmt sind, kann man das aber möglicherweise ausschließen. Schließlich müssen wir Korrektheit nicht unbedingt generell abstrakt feststellen, sondern können uns auch mit einer konkreten Implementation und Umgebung zufrieden geben.
push_back ist doch dann ein idealer Kandidat für eine Exception, da vielleicht Speicher allokiert werden muss...
richtig, aber vielleicht garantiert die umgebung ja, dass das nicht passiert.
vielleicht, vielleicht auch nicht. Wer kann das schon sagen, ohne nähere Details zu kennen? new war ja nun nur als Beispiel gedacht. Letztlich kann in C++ doch so ziemlich alles werfen. Nehmen wir mal an, man würde Zeiger auf Objekte abgeleiteter Klassen in den Vector legen (ein wesentlicher Grund Pointer zu benutzen). Dieses Konzept ist erweiterbar, d.h. es können jederzeit neue Klassen hinzukommen, die wohlmöglich nicht der Kontrolle des ursprünglichen Autors unterstehen. Eine solche Klasse könnte irgendwo eine Exception werfen, selbst wenn die urspürnglichen Klassen das nicht tun.
Ok, ich weiß, das war nicht gefragt. Ich weiß auch, das diese Situation nicht zwangsläufig auftreten muß (man könnte zum Beispiel in die Dokumentation der ursprünglichen Klassen schreiben, daß sie nciht werfen dürfen). Aber das wissen wir nicht, weil wir nur dieses winzige Code-Stück gesehen haben.
Daher bin ich der Meinung, daß man, wenn möglich, eine Antwort geben sollte, die Allgemeingültigkeit besitzt, d.h. für alle möglichen Situationen und Implementierungen der relevanten Klassen gilt.
Simon2 schrieb:
Oder den threadsafen, der aber nicht performanceoptimiert ist.
Oder den performanceoptimierten, der aber schwer erweiterbar ist.Was bitte hat Performance mit Korrektheit zu tun?
Simon2 schrieb:
Auch hier nochmal: Möchtest Du einem Einsteiger exception-safety erklären (wogegen ich gar nichts habe), dann tue es auch
Nein, möchte ich eigentlich nicht. Ich glaube es nicht, daß es eine gute Idee ist, einen Einsteiger zu früh mit zuvielen komplexen Aspekten der Sprache zu belasten. Aber ich bin auch der Meinung, daß man einem Einsteiger, wenn man die Wahl zwischen einer Exception-sicheren Methode und einer nicht Exception-sicheren Methode hat, die Exception-sichere Methode an die Hand geben sollte (nebenbei bemerkt, die SmartPointer haben an dieser Stelle ja auch noch andere Vorteile als nur die Exception-Sicherheit).
Simon2 schrieb:
.. und bei einem simplen "einmal-durchlauf-Programm" auf einem modernen Betriebssystem, spricht nichts dagegen, nach einer Ausnahme den Speicher vom OS aufräumen zu lassen.
Das sehe ich etwas anders, aber meinetwegen (müssen das Thema ja nicht totreden). Das ist eigentlich auch gar nicht mein Punkt. Aber:
- was passiert, wenn im Destruktor des "leakenden" Objekts noch andere System-Resourcen freigegeben werden? System-Resourcen, die weitaus beschränkter sind als Speicher und wo bei einem einmaligen Leak bereits die verfügbaren Resourcen erschöpft sind?
- was passiert, wenn es kein simples "einmal-durchlauf-Programm" ist?
Wir wissen schließlich nicht, was der Fragesteller da gerade schreibt (auch wenn ein "einmal-durchlauf-Programm" schon wahrscheinlicher ist). Ist es wirklich klug ihm jetzt einen Code an die Hand zu geben, bei dem er später im Verlauf seines Lernprozesses feststellt, daß der es in vielen Situationen gar nicht tut? Da geben wir ihm doch lieber gleich jetzt die SmartPointer (auf Exception-Sicherheit muß man dabei ja nicht herumreiten).
-
Performancetechnisch wäre die Reihenfolge wohl besser.
for(int i=0;i<5;++i) { vectorB.push_back(A()); //ohne 'new' - das Objekt wird direkt im vector auf dem Stack angelegt // ... a mit Werten füllen über vectorB.back(); }
-
newly schrieb:
...
in java ungefähr sofor (int i=0;i<5;i++){ A a=new a(); vectorB.add(a); }...alle objekte sind verschieden.
...... instantiieren aber alle dieselbe Klasse. Ist es wirklich das, was Du willst (unterschiedliche Objektidentitäten aber identische Objektklasse) ?
Dann hat das nichts mit Polymorphie zu tun.
Die kommt erst ins Spiel, wenn Du mit Objekten unterschiedlichr Klassen (also z.B. A und
arbeiten willst. Aber das ist in C++ eigentlich nicht anders als in Java (außer, dass vector typsicher(er) ist, d.h. Du kannst nicht beliebige Objekte reinpacken).Gruß,
Simon2.