Frage zur Legitimität meines Programmausschnittes ;)
-
Sicher? Ich sehe eher ein Problem dabei, dass das verkleinerte Array genauso viele Elemente wie das Ausgangsarray hat. Vielleicht verstehe ich dich auch falsch. Kannst Du einfach deine Version nochmal posten ? :p
Nunja, wenn ich eine Element aus einem Array rausnehme, dann sollte es auch verkleinert werden, da sonst ein nicht initialisiertes Element vorhanden ist!?
Liebe Grüße
freakC++
-
Das ist überhaupt kein Problem, jedesmal ein neues Array zu erstellen ist dagegen ein ungeheures Performanzproblem.
-
freakC++ schrieb:
@unskilled: Deine Version funktioniert so nicht. Du erstellst einfach ein Array mit der gleichen Größe. Das hat dann zur Folge, dass da zu löschende Element undefiniert ist. Genau das gleiche gilt dann auch für Athars Version.
Moment mal. Woher willst du wissen, dass es da genau ein undefiniertes Element gibt? Alles was du zu einem bestimmten Zeitpunkt hast ist folgendes:
- einen Zeiger irgendwohin
- eine Zahl lng
- eine Zusicherung, dass ab diesem Zeiger lng Objekte des Typs int liegen
Keins davon ist undefiniert. Wenn du jetzt meinst, das dahinter wäre undefiniert, dann frag ich dich, und was ist mit dem DAhinter? Es ist nicht sinnvoll, zwischen den Elementen außerhalb des Bereiches 0..lng-1 danach zu unterscheiden, ob sie irgendwann mal im Array waren oder nicht.
Zu wollen dass das Array schrumpft ist legitim, um keinen Speicher zu verschwenden (ob sich das wirklich lohnt ist die andere Frage), aber mit der Definiertheit der Elemente hat es nichts zu tun.
-
Das stimmt schon, aber ich man könnte sonst auf ein initialisiertes Element zugreifen.
/edit: @Bashar: Naja, wenn ich ein Element lösche, das Array aber nicht verkleiner, dann steht in diesem Element Müll, oder?
Ach man...ich will das einfach *imKreisHüpf*

Danke
lg, freakC++
-
freakC++ schrieb:
Sicher? Ich sehe eher ein Problem dabei, dass das verkleinerte Array genauso viele Elemente wie das Ausgangsarray hat. Vielleicht verstehe ich dich auch falsch. Kannst Du einfach deine Version nochmal posten ? :p
void delete_element(int index_to_delete) { int* tmp = new int[lng-1]; for(int i = 0; i != index_to_delete; ++i) tmp[i] = arr[i]; for(int i = index_to_delete+1; i != lng; ++i) tmp[i-1] = arr[i]; using std::swap; swap(tmp, arr); --lng; delete[] tmp; }Nunja, wenn ich eine Element aus einem Array rausnehme, dann sollte es auch verkleinert werden, da sonst ein nicht initialisiertes Element vorhanden ist!?
Nö - es wurde ja mal initialisiert - außerdem steht doch nirgendwo, dass du auf das element zugreifen sollst?!
void delete_element(int index_to_delete) { --lng; if(index_to_delete == lng) return; using std::swap; swap(arr[index_to_delete], arr[lng]); }bb
-
Da haste wiederum recht. Aber in deiner neuen Version, verringerst Du lng, weshalb das temp Array und letztendlich das ursprüngliche Array "arr" verkleinert wird. So wie ich es haben wollte.

Vielen Dank
lg, freakC++
-
Dass du Speicher sparst, wenn du das Array immer passend schrumpfst, ist auch ein Trugschluß, zumindest wenn du ab und zu Elemente löschst.
Denn kurzzeitig wird für temp zusätzlicher Speicher in Größe des ursprünglichen Arrays(-1...) benötigt. Dieses "kurzzeitig" hat es in sich, denn:
1. wenn Speicherknappheit herrscht, muss dieser Speicher erst geschaffen werden, indem andere Seiten ausgelagert werden. Dann ist das schon gar nicht mehr so kurzzeitig und die bei der Aktion betroffenen Programme haben später das Nachsehen.
2. wenn genug Speicher da ist, muss ein ensprechend großer Teil des Filecaches verworfen werden. Auch wenn der Speicher nur sehr kurz benötigt wird, bleibt der "Schaden" natürlich auch nach dem Freigeben bestehen.Wenn deine Arrays immer sehr klein sein werden, sind diese Überlegungen natürlich uninteressant, dann gilt das aber für Speicher sparen allgemein.
-
Heißt das, dass ich zukünftig ohne Hilfsarray arbeiten soll und dann eventuell undefinierte Elemente in Kauf nehmen soll. Dein Begründung leuchtet mir nämlich ein.
Wenn ich jedoch aus einem riesigen Array ganz viele Elemente lösche, dann habe ich nach dem erfolgreichen Löschvorgang nicht mehr so viel Speicher belegt (ich betrachte nur vorher und nachher). Das ist dann jedoch kein Trugschluss mehr ?!
Vielen Dank
lg, freakC++
-
freakC++ schrieb:
Heißt das, dass ich zukünftig ohne Hilfsarray arbeiten soll und dann eventuell undefinierte Elemente in Kauf nehmen soll. Dein Begründung leuchtet mir nämlich ein.
Die Elemente, die undefiniert sind, sind außerhalb des benutzten Bereichs, ist also egal. Alle Implementationen von dynamischen Arrays, ob std::vector oder etwas anderes unterscheiden zwischen der Kapazität (für wie viele Elemente Speicher angefordert wurde) und der "Größe", also wie viele Elemente davon wirklich benutzt werden. Dass die letzten Elemente undefiniert sind, macht nichts, da sie formell nicht existieren und der Zugriff nicht erlaubt ist.
Beim Löschen sollte man also kein Hilfsarray erstellen, sondern die Elemente in-place nachrücken. Dann verringert sich die Größe, die Kapazität bleibt aber gleich. Natürlich kannst du die Kapazität trotzdem verringern, aber nur wenn sie z.B. doppelt so groß ist wie die Größe. Dann "lohnt" es sich allmählich.freakC++ schrieb:
Wenn ich jedoch aus einem riesigen Array ganz viele Elemente lösche, dann habe ich nach dem erfolgreichen Löschvorgang nicht mehr so viel Speicher belegt (ich betrachte nur vorher und nachher). Das ist dann jedoch kein Trugschluss mehr ?!
Ja, wenn du nach dem "großen" Löschvorgang nichts mehr löschst, dann füllt sich der Filecache bald wieder.
-
freakC++ schrieb:
Wenn ich jedoch aus einem riesigen Array ganz viele Elemente lösche, dann habe ich nach dem erfolgreichen Löschvorgang nicht mehr so viel Speicher belegt (ich betrachte nur vorher und nachher). Das ist dann jedoch kein Trugschluss mehr ?!
Doch, könnte immer noch einer sein. Denn ob der Speicher bereits schon wieder an das System zurückgegeben wird, ist auch nicht unbedingt garantiert.
Zudem, wie schon Athar gesagt hat:
1. Wenn du grössere Arrays hast, dann ist diese Methode extrem schlecht, da du temporär plötzlich das doppelte an Speicher benötigst.
2. Wenn du kleinere Arrays hast, dann ist es eine völlig unnötige Aktion und verschwendet nur Performance.Und zuletzt: Verwende gleich
std::vector, der macht diese Umkopierereien ganz alleine. Oder wenn du unbedingt aus einem völlig verhexten und unlogischen Grund bei deinem C Array bleiben willst, verwendestd::copy:void delete_element(int index) { /* Fehlerabfrage? */ // Verschiebe die Elemente hinter index um eins nach vorne. std::copy(arr + index + 1, arr + lng, arr + index); --lng; }Die Version von unskilled verändert nämlich die Reihenfolge der Objekte. Ich weiss nicht, ob das gewünscht ist.
Grüssli
-
freakC++ schrieb:
/edit: @Bashar: Naja, wenn ich ein Element lösche, das Array aber nicht verkleiner, dann steht in diesem Element Müll, oder?
Wie kannst du ein Element löschen, ohne das Array (oder zumindest die offizielle Grösse, also die benutzte Anzahl Elemente) zu verkleinern?
-
Ich habe mich ein bisschen unverständlich ausgedrückt. Ich meine, wenn ich den Inhalt eines Elements lösche. Dann steht da nur noch Müll drin.
Athar schlug vor, dass ich kein Hilfsarray nutzen soll, die Elemente in-place nachrücken soll. Ich weiß zwar was in-place bedeutet, doch kann ich mir momentan hier keinen Reim drauf machen. Wie würde das denn hier dann aussehen?
Vielen Dank
lg, freakC++
-
freakC++ schrieb:
Ich habe mich ein bisschen unverständlich ausgedrückt. Ich meine, wenn ich den Inhalt eines Elements lösche. Dann steht da nur noch Müll drin.
Du drückst dich immer noch unverständlich aus. Wie löschst du den Inhalt eines Elementes?
freakC++ schrieb:
Athar schlug vor, dass ich kein Hilfsarray nutzen soll, die Elemente in-place nachrücken soll. Ich weiß zwar was in-place bedeutet, doch kann ich mir momentan hier keinen Reim drauf machen. Wie würde das denn hier dann aussehen?
Siehe zum Beispiel meinen Quellcode-Vorschlag.
Grüssli
-
Ich habe ein Array, dass Zeiger auf Objekte beinhaltet. Wenn ich nun ein Objekt lösche, dann zeigt der Zeiger auf das Nichts. Das meine ich damit.
Danke!
lg, freakC++
-
freakC++ schrieb:
Ich habe ein Array, dass Zeiger auf Objekte beinhaltet. Wenn ich nun ein Objekt lösche, dann zeigt der Zeiger auf das Nichts. Das meine ich damit.
Achso, du hast ein Array von Zeigern, sag das doch.

Der Zeiger zeigt dann aber nicht auf das Nichts, sondern einfach immer noch auf die Speicherstelle, wo früher das Objekt war, welches nun ungültig ist. Womöglich steht dort sogar immer noch das Objekt. Ist halt undefiniert, was dort nun steht.Allerdings habe ich gerade den Überblick verloren, in welchem Zusammenhang das nun wieder war. Ist ja eigentlich egal, was dort nun steht, es interessiert dich ja nicht mehr.

Grüssli