Länge von Arrays einlesen



  • Mir ist das malloc viel lieber, da man da mehr Freiheiten am Speicher hat.

    Klar also vergleichen wir mal die Folgenden beiden Zeilen

    void * foo = malloc (100);
    void * bar = ::operator new (100);
    

    @daishi:
    Ich sehe grade den Unterschied nicht, aber du kannst ihn mir sicher erklären.



  • @Helium
    Zeig mir mal bitte wie ich das mit new einfach machen kann.

    int n=5;
    int *feld;
    feld=(int*)malloc(n*sizeof(int));
    feld=(int*)realloc(feld,2*n*sizeof(int));
    

    Es sollte Dir klar sein, daß zu malloc noch realloc, free, calloc ... gehören.
    Bei new habe ich nur noch delete.



  • Und dir ist sicher auch klar, dass man sich ganz einfach ein Realloc für C++ schreiben kann und dass man malloc-Rückgabewerte nicht casten sollte?



  • Wenn man unter Windows Programme schreibt, ist es sicherer die Rückgabewerte zucasten.
    Wegen der implementation von realloc, man kann das Rad auch neu erfinden.



  • @daishi! Ich habe nie C gelernt, bin gleich in C++ eingestiegen - kenne mich mit malloc etc. nicht aus. Aber selbst ich sehe, das ein realloc doch den alten Speicherbereicht auf den feld zeigt, umkopieren muß, oder? Wenn es diesen nicht umkopiert, dann muß ich sagen, kann realloc zaubern. 😮 Ich kann dein Bsp. jetzt nicht ausprobieren, aber nach dem realloc zeigt feld sicherlich auf einen anderen Speicher, oder?

    Jetzt willst du uns doch nicht erzählen, das das umkopieren eines Arrays über C schneller geht, als über ein new in C++ (welches überigens die gleiche Strategie fährt). Nur schlauerweise mache ich das mit std::vector, welches mir den ganzen Krempel von alleine re-newed (oh mein Gott, was für ein Wort - sorry), ohne das ich mich darum kümmern muß. Ganz davon abgesehen, das ein vector tausendmal sicherer ist und ich nicht in einen ungültigen Bereich schreiben kann.



  • int n=5; 
    int *feld; 
    feld=new int [n]; 
    {
       int * temp = feld=new int [2*n]; 
       std::copy(feld, feld + n, temp);
       delete [] feld;
       feld = temp;
    }
    

    Natürlich in 'ne Funktion packen und fertig.



  • Hab was ähnliches mit memcpy gebastelt.

    template<typename T>
    	T* reallocpp(T* ptr, size_t oldsize, size_t newsize)
    {
      T* rval = new T[newsize];
    	memcpy(rval, ptr, oldsize * sizeof(T));
    	delete[] ptr;
    	return rval;
    }
    
    int main(void)
    {
    	int* x = new int[12];
    	x[11] = 100;
    	x = reallocpp(x, 12, 16);
    	int c = x[11];
    	x[15] = 1;
    
    	return 0;
    }
    


  • Artchi schrieb:

    Jetzt willst du uns doch nicht erzählen, das das umkopieren eines Arrays über C schneller geht, als über ein new in C++ (welches überigens die gleiche Strategie fährt). Nur schlauerweise mache ich das mit std::vector, welches mir den ganzen Krempel von alleine re-newed (oh mein Gott, was für ein Wort - sorry), ohne das ich mich darum kümmern muß. Ganz davon abgesehen, das ein vector tausendmal sicherer ist und ich nicht in einen ungültigen Bereich schreiben kann.

    Das realloc intern das Feld umkopiert steht außer Frage, aber die Bemerkung mit dem Vector hättest Du Dir sparen können, da ein paar Beiträge vorher schon geklärt wurde, das ein Vector bei Größenveränderungen zu langsam ist.



  • Wie wäre es eigentlich sich new einfach zu überladen, um eben diese aufgabe zu erledigen? Ich würde allerdings zu std::copy statt std::memcpy greifen, da man auch nicht-PODs verwenden könnte. Man kann ja nachher auch mit Traits optimieren, os dass bei PODs std::memcpy verwendet wird.



  • Das realloc intern das Feld umkopiert steht außer Frage, aber die Bemerkung mit dem Vector hättest Du Dir sparen können, da ein paar Beiträge vorher schon geklärt wurde, das ein Vector bei Größenveränderungen zu langsam ist.

    Dann habe ich es nicht mitbekommen. Könntest du nochmal Zitieren, was genau du meinst. Wenn es um schnelle Größenänderungen geht, geht wohl nichts über verkettete Listen. Alles, was Vektoriell ist, ist viel zu lahm.



  • @Helium

    RHBaum schrieb:

    @MaSTaH

    malloc/realloc/free ist C. In C++ verwendet man new/delete. Wenn man dynamisch langen Speicher braucht nimmt man kein realloc sondern einfach einen vector.

    Wenn es um zeitkritische sachen geht, fliegst aber mit Vector auf die Nase ! 😃 Vector ist nun mal saulangsam, wenn es um Groessenaenderungen geht. Viele weichen aus dem Grunde auf C in solchen faellen aus.
    das selbe ist mit new. new und malloc kannst ned vergleichen. new macht ne ganze menge mehr. Deshalb ists auch wirklich langsamer. Bei zeitkritischen sachen kann man auch dann auch wieder auf malloc ausweichen.
    Es gibt in der Literatur auch Themen die sich mit dem Optimieren von C++ beschaeftigen, dort werden zum beispiel die new/delete operatoren von atomaren Klassen ueberschrieben und mit malloc realisiert, Gerade bei kleinen und vielen objekten bringt das nen performance boost.

    Aber pronzipiell hast Du Recht, solchen "Schmutz" sollt man nur machen, wenn mans wirklich braucht. Lieber auf 3% Prozessorlast verzichten, dafuer sichereren und wiederverwertbareren code schreiben ... Dein projektmanager wird dirs danken :p

    Ciao ...

    Diesen Beitrag meinte ich, wenn du weiter im Forum suchst, findest Du auch eine genauere Beschreibung.
    Du kannst die aber auch mal die Implementierung des Vectors ansehen, da wirst Du dann auch schlau.



  • MaSTaH schrieb:

    dass man malloc-Rückgabewerte nicht casten sollte?

    Was erzählst du? Man *MUSS* malloc-Rückgabewerte in C++ casten, da es keine implizite Konvertierung von void* auf andere Pointertypen gibt.

    daishi schrieb:

    da ein paar Beiträge vorher schon geklärt wurde, das ein Vector bei Größenveränderungen zu langsam ist.

    Es wurde behauptet, nicht geklärt.



  • daishi schrieb:

    aber die Bemerkung mit dem Vector hättest Du Dir sparen können, da ein paar Beiträge vorher schon geklärt wurde, das ein Vector bei Größenveränderungen zu langsam ist.

    Ehem, behaupte ich etwa das ein vector langsamer als ein realloc ist??? Nö! Wie von mir bereits gesagt, steht in der Impelmetierungs-Vorgabe zur STL, das es keinen Performance-Verlust geben darf. Denn sonst macht das ganze keinen Sinn, die STL zu verwenden. In jedem STL-Buch und im Buch von Bjarne Stroustrup steht dies unmissverständlich drin.

    Bjarne Stroustrup schrieb:

    Most of these techniques are criticized unfairly for being inefficient. The assumption is that if it is elegant, if it is higher level, it must be slow. It could be slow in a few cases, so deal with those few cases at the lower level, but start at a higher level. In some cases, you simply don't have the overhead. For example, vectors really are as fast as arrays.

    Quelle: http://www.artima.com/intv/goldilocks.html

    Du kannst ja gerne Bjarne Stroustrup widersprechen. 😃

    Ich kann das Interview nur empfehlen, vorallem die erste Seite passt zu diesem Topic wie die Faust aufs Auge!



  • @Artchi
    Da steht doch nur, da ein Vector genauso schnell wie ein Array ist.
    Über den Aufwand, der für die Speicherallocierung nötig ist steht da nichts.

    Ich habe mich ja auch nicht über die Geschwindigkeit des Vectors allgemein ausgelassen, sondern nur über die beim ver-größern/kleinern der Elementanzahl.

    Aber gut. (und aus)



  • vorallem die erste Seite passt zu diesem Topic wie die Faust aufs Auge!

    Genau, und was in den Buechern ned steht, ist der Zusammenhang wischen implementationsdetails und der Geschwindigkeit ...

    Ok, bevor wir uns darueber den kopp einschlagen, sollte man das Getreu Bashar's Grundregel erst mal messen ...

    Schreib nen Programm, das nen vector von nem anfang von 1000 elementen vom Typ int .... in 10er schritten auf 100000 erhoeht ... und dann wieder erniedrigt, so oft, bist laufzeiten im sekundenbereich bekommst, um gescheit messen zu koennen.

    Dann ersetzt den vector durch nen Array, mit dem genau das selbe machst, von 1000 anfangen, in 10er schritten erhoehen , und wieder runter auf 1000.
    Dabei das umkopieren der Werte nicht vergessen, die muessen ja gleich bleiben ...

    Ich schatze mal genau hier wird Bashar dann zwischenrufen -> bei mir machts kaum nen unterschied ! :p
    Aber teste es mal mit der M$ Impl, und dann ersetz die mal durch den STLport ...
    Und es wird sogar ein oder mehrere Implementationen geben, wo der Vector enorm schneller ist als die Array Variante. (Dafuer aber im Zugriff auf die elemente selber etwas langsamer 😃 ) !!!

    Ich denke die Unterschiede fallen ned so gravierend aus ... aber ich behaupte es gibt sie ... (u.a. nutze ich deswegen den stlport)

    steht in der Impelmetierungs-Vorgabe zur STL, das es keinen Performance-Verlust geben darf.

    Aehm, warum gibts bei den Implementierungen dann unterschiede ? Wenn alle Implementierungen gleich sind, warum gibts dann unterschiedliche Implementierungen ? Wenn sich keiner an die Statdards haelt ... ists dann nen wunder das sich die Standards net wie gewuenscht verbreiten ???

    Vector ist eh nen eigenes Problem. Das Problem liegt eigentlich im Komfort. Die leute nehmen Vector, weil sie zu "bequem" sind, ist ja auch ok, dafuer isser ja auch da ...
    Dann stellens fest, das ihre SW zu lahm ist, und merken, das bei ihrem Vector ne ganze Menge CPU Waerme verbraten wird. Aber anstatt weiter zu ueberlegen, und den Vector zu optimieren, sprich ihm die Zuegel aus der Hand zu nehmen, wenns um die Groessenanpassung geht, steigens lieber gleich auf Arrays um.

    So ist leider die Praxis. Die Leute, die die Container falsch einsetzen, statt ner Liste nen vector nehmen etc. noch gar nicht zugerechnet.

    Mit dem Geschwindigkeitsunterschied von Array und Vector duerften sich eigentlich nur Leute rausreden, wo es wirklich um auf jeden rechentakt ankommt. Treiber werden eh fast nur in C geschrieben, SW fuer kleinere Microcontroller aus aehnlichen gruenden auch ...
    Also sollte man sowas in erwaegung ziehen, wenn es um frameraten geht ... sonst eher nich ...
    Wobei es dann immer noch eine Erwaegung wert ist, den zeitkritischen Anteil in ne eigene Lib auszulagern und die komplett in C zu schreiben ...

    Ciao ...



  • Bashar schrieb:

    Was erzählst du? Man *MUSS* malloc-Rückgabewerte in C++ casten, da es keine implizite Konvertierung von void* auf andere Pointertypen gibt.

    Mir ist schon klar, dass es in C++ sonst nicht geht (ganz im Gegensatz zu C, wo dies implizit geschieht). Wie denn auch? Ich meinte nur, dass man in C++ in jedem Fall malloc vermeiden sollte, weil es unsicher ist von void* nach X* zu casten. Das sind nämlich Stellen an denen man leicht auf die Schautze fällt. Ich meine das auch in den Stroustrup FAQ gelesen zu haben. Ich lasse mich aber gerne eines besseren belehren, wenn jemand den Beweis antritt, dass malloc wirklich so viel schneller als new ist, wie behauptet wird.



  • Das ist ja ein anderes Thema. Klar sollte man malloc meiden. Aber wenn man es benutzt, dann muss man casten.



  • Ok, ist vielleicht nicht ganz rüber gekommen 😉 .



  • Zu "realloc vs. vector" gibt es gerade eine sehr ausführliche Diskussion in comp.lang.c++.moderated ("realloc in C++" glaube ich).

    IMHO ist die Frage zwischen C und C++ sowieso nicht die Wahl zwischen malloc oder new[], sondern zwischen dem Verwenden einer Wrapper-Klasse oder eines Zeigers, in den jegliche sonstige Semantik hineininterpretiert wird. Wenn malloc/realloc/free schneller sein sollten als new[] oder ein vector, kann man immer noch eine eigene, garantiert overhead-freie Wrapperklasse (podarray<T>?) schreiben, anstatt gleich völlig zu C überzugehen und mit exception-unsicheren Zeigern um sich zu werfen, die am Ende keiner mehr versteht.



  • Wer vectorielle Datentypen einsetzt, wenn es darauf ankommt schnell zu wachesen, der ist selber schuld. Was gibts da mehr zu sagen.


Anmelden zum Antworten