Frage zu auto_ptr und map der STL
-
Möchte darauf hinweisen, das du nur bei Polymorphie Pointer in deinem Container anlegen mußt. Sind die Objekte dagegen immer vom gleichen Typ, legst du halt keine Pointer an sondern den Typ selbst:
Ich weiß nicht ob ich das nun 100%ig verstanden haben:
In meinem Beispielprogramm nutze ich für die Klasse MeineKlasse keine Polymorphie, allerdings möchte ich die Objekte der Klasse im Heap speichern.
Wenn ich nun in der map keinen Pointer auf MeineKlasse benutze - werden dann die Instanzen nicht im Stack abgelegt ?
Und wie kann/muss ich die dann benutzen (so dass sie auf dem Heap liegen)?Mit Zeiger:
{ map<int, *MeineKlasse> MeineMap; //ein Objekt von MeineKlasse erstellen MeineKlasse* pObj = New MeineKlasse(parameter); map[3] = pObj; // viel Code... // Löschen der Objekte aus dem Heap: map<int, *MeineKlasse>::iterator iter; for(iter = MeineMap.begin(); iter != MeineMap.end(); iter++) { delete iter->Second; } } /* Gültigkeitsbereich von MeineMap verlassen, Speicher in Heap muss freigegeben sein */Ohne Zeiger:
//???
-
Illarion schrieb:
...
In meinem Beispielprogramm ...möchte ich die Objekte der Klasse im Heap speichern....=> Du musst Pointer verwenden.
Artchi wollte aber darauf hinweisen, dass es evtl. gar nicht nöig ist, die Objekte auf den Heap zu legen.Gruß,
Simon2.
-
Naja, kommt darauf an, was große Objekte sind? (vielleicht denkt er, die seien groß, und in Wirklichkeit langweilt sich die Runtime) Und wie oft wird etwas eingefügt? (gehts in dem Container wild und heiß her?) Also ich vermeide immer Pointer in Containern. Wenn ich weiß, das es in dem Container wild zu geht, mach ich mir schon Gedanken.
-
Ohne Pointer:
map<int, MeineKlasse> MeineMap; //ein Objekt von MeineKlasse erstellen MeineKlasse pObj(parameter); map[3] = pObj; }
-
Ok, vielen Dank euch allen für die nette, kompetente und schnelle Hilfe

Später werde ich mir hierfür noch andere SmartPointer ansehen, die das delete übernehmen und auch im Fall auftretender Exceptions den Speicher freigeben, vorerst ist es so aber völlig ausreichend

@Artchi: Die Objekte sind de facto nicht Groß, mir geht es eher um das Theoretische, das Gewusst-Wie
Ich habe ja erst vor ner knappen Woche mit C++ angefangen.
-
Artchi schrieb:
Naja, kommt darauf an, was große Objekte sind? (vielleicht denkt er, die seien groß, und in Wirklichkeit langweilt sich die Runtime)...
Deswegen meinte ich ja: Erstmal testen (und bis zum Beweis des Gegenteils davon ausgehen, dass es kein Problem ist mit Stackobjekten)! Vorher weiß man's nicht wirklich.
Etwas Anderes ist es noch, wenn man externe Ressourcen (Files, Connections, ...) verwaltet. In dem Fall kann das Kopieren einerseits konzeptionell als auch performancetechnisch ein Problem darstellen...
Aber das sind eher seltene Ausnahmen.Gruß,
Simon2.
-
Illarion schrieb:
Ok, vielen Dank euch allen für die nette, kompetente und schnelle Hilfe

Später werde ich mir hierfür noch andere SmartPointer ansehen, die das delete übernehmen und auch im Fall auftretender Exceptions den Speicher freigeben, vorerst ist es so aber völlig ausreichend

Hi,
dafür brauchst Du nicht unbedingt smart_pointer.
Es genügt, im Dtor des "Verwaltungsobjekts" (das die map beinhaltet und in dem die map gefüllt wird) die map durchzugehen und die Objekte zu deleten..Gruß,
Simon2.
-
Simon2 schrieb:
dafür brauchst Du nicht unbedingt smart_pointer.
Es genügt, im Dtor des "Verwaltungsobjekts" (das die map beinhaltet und in dem die map gefüllt wird) die map durchzugehen und die Objekte zu deleten..Gruß,
Simon2.
Genau so habe ich es nun auch gelöst

Wow C++ fängt an richtig Spaß zu machen. Aber der OOP-Ansatz ist wirklich eine riesige Umstellung zu Basic/Pascal... (eben was ich vorher benutzt habe)
-
Illarion schrieb:
......
Wow C++ fängt an richtig Spaß zu machen....
Oh Ja !!
*schwärm* 
Also ich finde, dass Du ganz gut auf dem Weg bist und habe nicht den Eindruck, dass Du Dich mit dem Umstieg besonders schwer tätest !
Weiter so !!

Gruß,
Simon2.
-
Wenn man die Standardlibrary benutzt und kennt, macht C++ auch Spaß.

-
Hierzu noch:
Simon2 schrieb:
Illarion schrieb:
...
In meinem Beispielprogramm ...möchte ich die Objekte der Klasse im Heap speichern....=> Du musst Pointer verwenden.
Landen die Objekte die die map allokiert etwa auf dem Stack? Und wenn ja, wie macht die map das bloss?

Was ich damit sagen will, die Container der Standardbibliothek verwalten den Speicher den ihre Mitglieder zweifellos brauchen doch auch (irgendwo) auf dem Heap, nur dass der Benutzer eben nicht mit new und delete in Kontakt kommt...
-
LordJaxom schrieb:
Was ich damit sagen will, die Container der Standardbibliothek verwalten den Speicher den ihre Mitglieder zweifellos brauchen doch auch (irgendwo) auf dem Heap, nur dass der Benutzer eben nicht mit new und delete in Kontakt kommt...
Hi, also wenn das stimmt, dann würde ich tatsächlich nur einen Pointer brauchen, wenn ich Polymorphie nutze (wegen der automatischen Typbestimmung und Funktionszuordnung durch die vtable - wenn ich das richtig verstanden habe).
Und wenn ich ein Objekt erstelle... (also bei Verwendung OHNE Zeiger, da keine Polymorphie)
//ein Objekt von MeineKlasse erstellen MeineKlasse Obj(parameter); map[3] = Obj;... wird also folglich der Kopierkonstruktor aufgerufen um das Objekt Obj zu kopieren und - verwaltet durch die Contaninerklasse map - auf dem Heap abzulegen. new / delete übernimmt map, ich brauche mich darum nicht zu kümmern.
Ist das nun so richrig

-
LordJaxom schrieb:
...
Landen die Objekte die die map allokiert etwa auf dem Stack? Und wenn ja, wie macht die map das bloss? ;)...template <typename keyT, typename valT> class myMap { pair<keyT, valT> static_vals[MAX_SIZE]; pair<keyT, valT> vals; size_t size; public: myMap() vals(static_vals), size(0) {} ...:p
Aber stimmt schon: Es ist weder besonders wahrscheinlich noch wirklich sinnvoll, dass es so gemacht wird (außer vllt. für kleine Eintragszahlen und ab einer gewissen Größe schwenkt er dann auf den Heap ... aber auch nicht besonders wahrscheinlich)...
Mein Schwerpunkt bei der Aussage war: Er wollte gerne (außerhalb der map) mit Heapobjekten hantieren (jedenfalls habe ich ihn so verstanden) ...
Gruß,
Simon2.
-
Simon2 schrieb:
Mein Schwerpunkt bei der Aussage war: Er wollte gerne (außerhalb der map) mit Heapobjekten hantieren (jedenfalls habe ich ihn so verstanden) ...
Wenn ich mich da jetzt mal drauf versteifen darf, dass mit "hantieren" nicht zwangsläufig new/delete gemeint ist: Geht doch auch so, solang das Objekt in der Map noch existiert
map<int, string> names; names[10] = "Sascha"; string* p = &names[10]; // <- Zeiger auf Objekt auf Heap, vorausgesetzt die Map nutzt den Heap, was wie bereits festgestellt ist der wahrscheinlichste Fall sein dürfte.@Simon2:
Aber nimm mich bitte nicht zu ernst
@Illarion:
Den äußerst unwahrscheinlichen Fall, dass die Map so wie von Simon skizziert angelegt ist, mal aussen vor gelassen, ist das so richtig
-
Simon2 schrieb:
Mein Schwerpunkt bei der Aussage war: Er wollte gerne (außerhalb der map) mit Heapobjekten hantieren (jedenfalls habe ich ihn so verstanden) ...
Vielleicht habe ich mich doch nicht deutlich genug ausgedrückt.
Die Objekte müssen nur "in der map liegen", also von außerhalb der map soll erst gar nicht auf diese Objekte zugegriffen werden. Jedoch ist es wichtig, dass die Objekte sich im Heap befinden.
*Uff* anstrengend - alles Neuland für mich, meine Kentnisse beruhen auf c++ - Tutorials wie Schornboeck und Volkards C++ Kurs.
Ich hoffe ich habs nun soweit alles verstanden^^
-
Jedoch ist es wichtig, dass die Objekte sich im Heap befinden.
Warum?
-
Artchi schrieb:
Jedoch ist es wichtig, dass die Objekte sich im Heap befinden.
Warum?
Weil ich verstehen möchte wie es funktioniert

In meinem Beispiel ist es tatsächlich irrelevant, was allerdings, wenn besagte Objekte riesig sind (vllcht durch lange Strings, viele Membervariable (Unterobjekte etc.)) ? (schwer riesig genauer zu definieren, z.B. 50 kByte pro Objekt)
Und wenn es dann noch entsprechend viele Objekte sind (10000+) ?Dann hab ich den Stack doch schnell voll und es lohnt auf den Heap auszuweichen.
-
Genau das meinte ich mit "Vielleicht denkt er nur, die Objekte sind groß.".
Also, ein std::string selbst ist auf dem Stack nur klein, da er intern die Zeichenkette selbst auf dem Heap anlegt. Wenn du so willst, ist es auch ein Smart-Pointer für Zeichenketten.

Mach mal folgendes:
#include <string> #include <map> int main() { std::map<int, std::string> mymap; for(int i=0; i<1000000; i++) { std::string str("Hallo hjdshdjshduszuwe, ende!"); mymap[i] = str; } }Und dann mal ausführen. Du wirst dich wundern.
Kannst auch Testhalber danach alles ausgeben, könnte aber bei 1 Mio. Strings lange dauern (ist langsam halt die Konsole).

-
Stimmt, dass die Klasse string den String im Heap speichert hatte ich gelesen.
Aber mir gehts wirklich nur um das Verstehen, das Gewußt-Wie. Alles theoretisch also. Später kann es ja trotzdem vorkommen, dass ein Objekt riesig wird und eben nicht alle Member von sich aus im Heap liegen wie die Klasse string. Also ist es eben nur eine theoretische Annahme: die Objekte der Klasse MeineKlasse sind riesig und gehören auf den Heap
Wenn die Containerklassen der STL sowieso Ihre "Second-Werte" (dummer Begriff, i know) im Heap speichern und die Verwaltung übernehmen, dann ist die Sache damit eh erledigt

Ich brauche keine Zeiger, kein new/delete und die Objekte liegen - dank map - auf dem Heap

-
Achja, bei 1 Mio. Strings braucht man natürlich genug RAM. Kann sein das es nicht klappt. Aber definitiv hat das nichts mit dem Stack zu tun. Habs hier auf einem 2 GB RAM PC mit MinGW getestet. Geht wunderbar.