PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : malloc, calloc, realloc, free VS new und delete


Gast
2005-11-20, 18:08:08
Ich hab ein kleines Beispielprogramm geschrieben, das den C und den C++ Weg der dynamischen Speicherverwaltung gegenüberstellt:

#include <iostream>
using namespace std;
#define CODE_STYLE 1
int main() {
#if (CODE_STYLE == 0)
int *zahl = (int *) calloc(2, sizeof(int));
#else
int *zahl = new int[2];
#endif
zahl[0] = 10;
zahl[1] = 20;
cout << zahl[0] << zahl[1] << endl;
#if (CODE_STYLE == 0)
zahl = (int *) realloc(zahl, 3 * sizeof(int));
#else
zahl = new int[3];
#endif
zahl[2] = 30;
cout << zahl[0] << zahl[1] << zahl[2] << endl;
#if (CODE_STYLE == 0)
free(zahl);
#else
delete[] zahl;
#endif
return 0;
}


Aber ein Problem hab ich noch, es scheint in C++ nichts zu geben, was mit realloc vergleichbar wäre.
Der Output des Programmes ist, wenn CODE_STYLE == 0 ist folgender:

1020
102030

Bei CODE_STYLE == 1 (die C++ Variante) allerdings:

1020
0030


was bedeutet, dass mein "new" Aufruf mein Array wieder geleert hat.

Ich würde mich gerne auf die C++ Funktionen umgewöhnen, da es doch wesentlich einfacher ist, aber ohne realloc oder etwas vergleichbares, kommt das für meine Zwecke einfach nicht in Frage. Ideen?

Coda
2005-11-20, 18:17:03
std::vector

Gast
2005-11-20, 19:30:23
kannst du mir ein beispiel zeigen, wie man das mit der vector klasse macht? finde in der art nichts

Coda
2005-11-20, 21:35:58
#include <iostream>
#include <vector>

int main()
{
std::vector<int> zahl(2);
zahl[0] = 10;
zahl[1] = 20;
std::cout << zahl[0] << zahl[1] << std::endl;
zahl.resize(3); // oder einfach:
zahl[2] = 30; // zahl.push_back(30);
std::cout << zahl[0] << zahl[1] << zahl[2] << std::endl;
}"return 0;" ist in main übrigens nicht nötig - das wird automatisch eingefügt.

del_4901
2005-11-21, 13:10:59
was findet ihr nur alles an vector, das Ding ist grottenlangsam!
Mit unter einer Seite Code pflück ich da was effizenteres hin, wenn man nicht grad drin sortiern muss.

Topic: man kann sich dynamisch ein größeres Array erzeugen, und das alte da reinkopiern und das alte dann löschen. Wenn man das array nicht ständig sortiern oder füllen muss, ist das Ding sauschnell im Zugriff.

Coda
2005-11-21, 13:39:51
was findet ihr nur alles an vector, das Ding ist grottenlangsam!Blödsinn. Zugriff ist exakt gleich schnell wie bei einem Array. Es findet keinerlei Bereichsüberprüfung statt.

Mit unter einer Seite Code pflück ich da was effizenteres hin, wenn man nicht grad drin sortiern muss.Das will ich sehen mein liebes Alphatier. Die STL ist bei den meisten Compiler-Distributionen übelst tot-optimiert.

Topic: man kann sich dynamisch ein größeres Array erzeugen, und das alte da reinkopiern und das alte dann löschen. Soso. Genau das macht std::vector auch.

Wenn man das array nicht ständig sortiern oder füllen muss, ist das Ding sauschnell im Zugriff.Richtig. Gleichschnell wie ein vector.

zeckensack
2005-11-21, 13:46:14
was findet ihr nur alles an vector, das Ding ist grottenlangsam!
Mit unter einer Seite Code pflück ich da was effizenteres hin, wenn man nicht grad drin sortiern muss.Wie bist du denn zu der Erkenntnis gelangt? Debug-Build?
Selbst beim in Hinsicht auf STL grottenüblen MSVC6 ist eine vector-Implementation dabei, die du mit einem Array nicht schlagen kannst, weil sie ein Array ist. Schau doch einfach mal in deinen vector-Header (suche nach operator []).
Topic: man kann sich dynamisch ein größeres Array erzeugen, und das alte da reinkopiern und das alte dann löschen. Wenn man das array nicht ständig sortiern oder füllen muss, ist das Ding sauschnell im Zugriff.Ja geil, erst sich über angeblich mangelnde Effizienz aufregen, und dann mit Kopieraktionen kommen. realloc hat ganz viel Potential besser zu sein als das was du dir so unter einem effizienten dynamischen Array vorstellst. Aber gerade davon wollte der Threadstarter ja erstmal wegkommen.

edit: habe ich wirklich 7 Minuten gebraucht um dieses Posting zu schreiben? :|

Coda
2005-11-21, 13:48:31
Wenigstens muss ich das nicht allein durchfechten zecke ;)

Merksatz: Verwende solange die Container der STL bis du etwas brauchst was sie nicht können. Du kannst sie nicht schlagen.

del_4901
2005-11-21, 14:00:06
und warum habe ich dann mit der vector STL ungefähr die hälte der frames als wenn ich meien eigene liste nehme? ... ansonnsten wurde niks am code geändert, nur das ich die Listen ausgetauscht habe wo ich meine Objekte zum zeichnen drin aufbewahre.

Die ursprüngliche Idee stammt von Peter Shirley und R. Keith Morley "Realistic Ray Tracing" ISBN 1-56881-198-5 Und da steht auch drin geschreiben wie langsam die STL doch ist.

Um nochmal aufs wesentliche zurückzukommen, ich hab die hälfte der Frames mit der STL ... das kann sich nicht um eine Messungenauigkeit handeln!

Coda
2005-11-21, 14:04:29
Äh du hast eine Liste mit einem vector ersetzt? Dafür gibts std::list.

std::vector ist mit Sicherheit nicht langsamer als ein dynamisch alloziertes Array. Das ist technisch nicht möglich.

zeckensack
2005-11-21, 14:12:03
Vsync? :|

Und was genau meinst du mit Liste? Linked list!=vector.

Ein vector hat exakt einen Nachteil ggü einem statischen Array ...class
HaufenA
{
public:
int zeug[32];
int plonk() { return(zeug[16]); }
};

vs

#include <vector>

class
HaufenB
{
public:
std::vector<int> zeug;
int plonk() { return(zeug[16]); }
};... und zwar ist zeug[16] in HaufenA=((int*)this)[16]. In HaufenB kommt eine Indirektion hinzu, weil innerhalb der Klasse nur ein Zeiger auf das erste Element gespeichert ist, nicht jedoch das Array selbst.

Wie gesagt, das betrifft nur statische Arrays. Wenn die Größe bekannt und konstant ist, dann ist das auch genau das was du brauchst, und du kannst dir den vector gerne an die Backe schmieren und für langsamer halten, denn dann ist er es auch.
Dieser Vorteil von HaufenA löst sich allerdings in Rauch auf sobald man auch dort ein dynamisches Array einbaut, denn dann kommt man nicht darum herum dort ebenfalls das Array auf den Heap zu schmeißen und innerhalb der Klasse mit einem Zeiger auf das erste Element zu arbyten. Ob man das nun händisch macht oder auf die STL zurückgreift ist maximal ein stilistischer Unterschied.

ScottManDeath
2005-11-21, 14:23:08
Jo, als erstes sollte man sich die passende Datenstruktur aussuchen, diese auch richtig einsetzen (Stichwort: Häufigkeit und Art, Position von Einfügen, Löschen, Iterieren...)

Danach kann man sehen, ob eine speziell angepasste Version wirklich etwas bringt. Das geht aber nur mit einem Profiler, alles andere wäre Würfeln.

Wenn Deine STL Implementation suckt, dann teste eine andere (z.B. STLPort) oder investiere mehr Geld in Deinen Compiler. Templates sind nicht einfach, aber die Compiler werden besser, hatten ja schließlich auch seit 1998 Zeit ;)

Und ein std::vector ist nicht (viel) mehr als ein dummes Array.

Coda
2005-11-21, 14:57:43
zecke da fehlt HaufenB() : zeug(32) {}

RoKo
2005-11-21, 17:26:27
Ich hatte auch mal erlebt, dass jemand std::vector langsam fand. Stattdessen Arrays zu verwenden beschleunigte seine Anwendung um das Vielfache.
Letztlich kam heraus, dass er zum Zugriff nicht operator[], sonder .at() benutzte.

Coda
2005-11-21, 17:29:55
Apropos. Ich fände es mal sinnvoll wenn es eine Debug-STL geben würde die für operator[](int) at(int) benützt!

ScottManDeath
2005-11-21, 22:03:56
Afaik hat die VS 2k5 STL eine Debug Implementation und noch eine mit container_type::checked_iterator, die gucken ob es koscher zu geht ;) Kann noch nicht selbst gucken, da ich erst über Weihnachten migriere; ich möchte mir während des Semesters nicht meine Entwicklungsumgebung zerschießen :(

Gast
2005-11-21, 22:20:36
wow, danke für die vielen antworten ;)

hab aber noch ne frage zu vectoren.
wenn ich einen initialisiere, wird dann automatisch speicher für den allociert?

also so:

vector<int> zahl(2);


macht das ein "new" überflüssig?

noch ne frage, gibt es dazu noch etwas wie "delete", "free" oder was funktional ähnliches?

Coda
2005-11-21, 22:24:31
vector verwaltet seine Größe selbsständig, wenn du vector<int> zahl(2); erzeugst wird für 2 ints im Konstruktor Platz reserviert. Der Destructor gibt den Speicher wieder frei.

Falls dir Konstruktor und Destruktor nichts sagen solltest du dich erstmal damit beschäftigen.

Gast
2005-11-21, 22:40:14
tun sie, tun sie. bin nur grad dabei, mein programmieren zu revolutionieren, und cpp endlich in cpp zu schreiben. danke für eure hilfe, damit ist mein problem gelöst!

Gast
2005-11-21, 23:01:52
hm, doch noch ne frage.

der deconstructor wird ja aufgerufen, wenn ich delete aufrufe. das geht afaik nur mit objekten, die pointer sind.

also müsste ich meinen vector folgendermassen initialisieren:

std::vector<int> *v1 = new std::vector<int>;

jetzt kann ich ihm keine feste grösse zuweisen, er fängt also mit 0 an. (v1->resize klappt aber, hätte es nur gerne bei der initialisierung dabei)

aber das grösste problem, ich kann nicht mit operator [] auf die einzelnen elemente zugreifen.

für die ausgabe klappt das (langsame?) at(position) natürlich, aber wenn ich etwas in eine bestimmte stelle schreiben möchte, z. B. 12452, dann muss ich mir einen iterator dafür holen, und den entsprechenden wert dann so überschreiben, ein einfaches v1[12452] = 1; klappt ja nicht.

und alles nur für mein:

delete v1;


(gehen wir mal einfach davon aus, dass ich unbedingt mitten in meinem programm den allokierten speicher eines arrays freigeben muss)

Coda
2005-11-21, 23:04:46
der deconstructor wird ja aufgerufen, wenn ich delete aufrufe. das geht afaik nur mit objekten, die pointer sind.Nein, der wird auch aufgerufen wenn ein Objekt seinen Gültigkeitsbereich verlässt.

Den Code den ich dir gegeben habe funktioniert so.

jetzt kann ich ihm keine feste grösse zuweisen, er fängt also mit 0 an. Doch kannst du, allerdings ist das hier einfach nicht sinnvoll.
std::vector<int> *v1 = new std::vector<int>(2);aber das grösste problem, ich kann nicht mit operator [] auf die einzelnen elemente zugreifen.Doch kannst du auch
(*v1)[1] = 2;Aber wie gesagt brauchst du den Vektor nicht auf dem Heap allozieren damit seine Elemente freigegeben werden.