stackobjekte und new



  • mit A a = A(n) auf dem stack erzeugt wird

    Wie mein Vorposter schon gesagt hat, erzeugst du das Array mit new , welches immer vom Heap allokiert (wenn überhaupt).

    Pria schrieb:

    ist das hier auch so oder
    löst sich das von selbst?

    Nein, das löst sich nicht von selbst. Deswegen benutzt man new immer mit RAII. Oder am Besten gar nicht.

    Aus genau dem Grund verwirfst du bitte diesen unfassbaren Teufelsschmaus* und verwendest einen STL-Container.

    struct A
    {
      public:
        std::vector<A> childs;
    
        A() : childs(0) {}
    
        // Bzw. std::vector<A>::size_type
        A(std::size_t ct) : childs(ct) {}
    };
    

    Außerdem sind elaborated type specifier in C++ nicht mehr Pflicht, daher ist dieses typedef struct -Idiom nicht nötig.

    *char für die Anzahl?



  • Sone schrieb:

    Aus genau dem Grund verwirfst du bitte diesen unfassbaren Teufelsschmaus* und verwendest einen STL-Container

    Nein! Ich brauch die Geschwindigkeit die mir ein vector oder list nicht bieten kann.

    Sone schrieb:

    char für die Anzahl?

    Ist nie höher als 255 daher speichertechnisch besser



  • Pria schrieb:

    Nein! Ich brauch die Geschwindigkeit die mir ein vector oder list nicht bieten kann.

    Dann also:

    ...
    public:
       ...
       ~A(){delete [] childs;}
       ...
    


  • Ja klar, bau ich gerade ein bzw. ein Dispose()



  • Pria schrieb:

    Ich brauch die Geschwindigkeit […] daher speichertechnisch besser

    Bei welcher Anwendung hast du denn derartige Anforderungen an Geschwindigkeit und Speicherverbrauch? Es handelt sich hier bestenfalls um ein paar Takte ( vector und new[] sollten quasi identisch sein) und wenige zusätzliche Byte, für die du auf viel Fehlersicherheit und Komfort verzichtest (du brauchst nämlich, wenn du es manuell machst, auch noch einen Copy-Ctor und einen Zuweisungoperator, dazu musst du ständig wegen Exceptions aufpassen usw.).



  • ipsec schrieb:

    Es handelt sich hier bestenfalls um ein paar Takte ( vector und new[] sollten quasi identisch sein)

    Laut meiner Messung mit QueryPerformanceCounter ist .push_back um etwa 1/3 langsamer als eine Pointerzuweisung wenn ich keine geeignete Listengröße vorgebe, da ich diese aber kenne, da diese statisch pro durchgang bekannt ist kann ich genausogut ein * Array nehmen und mit ++ durchiterieren.



  • Wenn du die größe kennst, kannst du per vector::reserve() auch den Speicher im vorhinein reservieren lassen, dann ist push_back nur noch eine zuweisung und ein ++.



  • Pria schrieb:

    Ja klar, bau ich gerade ein bzw. ein Dispose()

    Dispose()?
    Sprechen wir noch von C++ oder von was anderem wie Microsoft-C++ mit .net?



  • Pria schrieb:

    ipsec schrieb:

    Es handelt sich hier bestenfalls um ein paar Takte ( vector und new[] sollten quasi identisch sein)

    Laut meiner Messung mit QueryPerformanceCounter ist .push_back um etwa 1/3 langsamer als eine Pointerzuweisung wenn ich keine geeignete Listengröße vorgebe, da ich diese aber kenne, da diese statisch pro durchgang bekannt ist kann ich genausogut ein * Array nehmen und mit ++ durchiterieren.

    Bitte nur im Release-Modus mit allen Optimierungen messen, und nur mit ausgeschalteten Bereichsüberprüfungen.



  • Pria schrieb:

    ipsec schrieb:

    Es handelt sich hier bestenfalls um ein paar Takte ( vector und new[] sollten quasi identisch sein)

    Laut meiner Messung mit QueryPerformanceCounter ist .push_back um etwa 1/3 langsamer als eine Pointerzuweisung wenn ich keine geeignete Listengröße vorgebe, da ich diese aber kenne, da diese statisch pro durchgang bekannt ist kann ich genausogut ein * Array nehmen und mit ++ durchiterieren.

    Du verwendest ihn nur falsch. vector::push_back entspricht in etwa:

    void push_back(T const& elem)
    {
        if(is_storage_full())
        {
             get_larger_storage();
             copy_everything_to_new_storage();
             destroy_old_storage();
        }
    
        insert_at_end(elem);
    }
    

    Was du vermutlich möchtest ist

    a.)

    vector<unsigned> v;
    v.reserve(N);
    for(unsigned i = 0; i < N; ++i)
        v.push_back(i);
    

    b.)

    vector<unsigned> v;
    v.resize(N);
    for(unsigned i = 0; i < N; ++i)
        v[i] = i;
    


  • Pria schrieb:

    Nein! Ich brauch die Geschwindigkeit die mir ein vector oder list nicht bieten kann.

    Wie schon von mehreren Geschrieben ist deine Aussage Unsinn. Die C++ Standardbibliothek ist in erster Linie auf Geschwindigkeit ausgelegt, man sollte aber auch wissen, wie man diese einsetzt.

    Wenn man sie falsch einsetzt (oder gar im Debug testet), kommt natürlich Unsinn raus. In deinem Fall ist deine Variante sogar höchst gefährlich.

    1. Verwendest du Zeiger/new/delete ohne zu wissen was du tust
    2. Würde in deiner Variante ein Destruktor alleine auch nicht reichen (Du müsstest entweder noch den Kopierkonstruktor/Zuweisungsoperator mitliefern, oder selbige unterbinden)...

    Pria schrieb:

    Sone schrieb:

    char für die Anzahl?

    Ist nie höher als 255 daher speichertechnisch besser

    Einerseits redest du von Performance, anderseits möchtest du auf Speicher hin optimieren?



  • asc schrieb:

    Pria schrieb:

    Sone schrieb:

    char für die Anzahl?

    Ist nie höher als 255 daher speichertechnisch besser

    Einerseits redest du von Performance, anderseits möchtest du auf Speicher hin optimieren?

    Beides geht nämlich nicht.
    Entweder du berechnest die Länge eines Strings anhand einer Schleife bei jedem length() Aufruf oder du speicherst sie als Member. Die eine Version ist speicherfreundlich, die andere schnell.

    Wozu brauchst du die Optimierung? Optimiere erst, wenn alles fertig ist und dein Programm zu langsam ist. Und dann nur die Parts, die am meisten etwas ausmachen und nicht alles (80/20-Regel).



  • wenn es eine Number Cruncher Software ist, muß man schon ganz am Anfang 100% optimieren, siehe z.B. hier:

    http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2271.html



  • dd++ schrieb:

    wenn es eine Number Cruncher Software ist, muß man schon ganz am Anfang 100% optimieren

    Aber ganz sicher nicht mit operator new[] . Der ist saulahm.



  • Jap. POD-Arrays legt man auch in C++ lieber mit malloc an wenn jeder Furz an Performance zählt da malloc keine Konstruktoren aufruft.



  • Seit wann ruft new[] bei POD-Typen (nach C++98) Konstruktoren auf?

    Ausserdem kann man, wenn man Konstruktoren definiert, auch eine Uninitialized-Version anbieten.


  • Mod

    Ethon schrieb:

    Jap. POD-Arrays legt man auch in C++ lieber mit malloc an wenn jeder Furz an Performance zählt da malloc keine Konstruktoren aufruft.

    Ähh, new auch nicht, wenn's nicht nötig ist. Und wenn's doch nötig ist, dann ist es nötig 😉 und man muss new nehmen.

    Wie sollte new denn auch bei POD einen Konstruktor aufrufen? Es gibt schließlich keinen.

    P.S.: Geht es nur mir so oder hat noch jemand anderes das Gefühl, dass der TE sich hier selber das Leben schwer macht? Widersprüchliche Optimierungsstrategien, Messungen offensichtlich im Debugmodus durchgeführt, mythische Ansichten über die Standardbibliothek. Klingt alles so, als habe jemand mal davon gehört, dass Optimierung ganz was tolles ist, ein paar Tricks gesehen, aber nicht verstanden hat.



  • SeppJ schrieb:

    P.S.: Geht es nur mir so oder hat noch jemand anderes das Gefühl, dass der TE sich hier selber das Leben schwer macht? Widersprüchliche Optimierungsstrategien, Messungen offensichtlich im Debugmodus durchgeführt, mythische Ansichten über die Standardbibliothek. Klingt alles so, als habe jemand mal davon gehört, dass Optimierung ganz was tolles ist, ein paar Tricks gesehen, aber nicht verstanden hat.

    Ja, "Ich brauch die Geschwindigkeit die mir ein vector oder list nicht bieten kann" sollte als erstes Alarmsignal ernst genommen werden.

    Ich hoffe, wir können Pria noch auf die gute Seite bringen.


Anmelden zum Antworten