Objekte zur Laufzeit



  • Hallo,

    ich habe zwei Klassen X und Y. X ist Aggregat der Y. Da ich noch nicht weiss wie viele Objekte der X ich in Y erzeugen muss, kann ich die X Objekte nur zur Laufzeit initialisieren. Ich möchte allerdings keines dieser Objekte auf dem Heap haben (also nix mit new erzeugen). Wie muss ich die Klasse Y aufbauen um diesen Aufbau zu realisieren?

    Danke für Vorschläge



  • Original erstellt von Sprotti:
    Ich möchte allerdings keines dieser Objekte auf dem Heap haben

    Das geht nicht.

    Da die Objektanzahl von X unbestimmt ist, wirst Du eine dynamische Speicherung benötigen. Diese legen den Speicher immer auf dem Heap ab, selbst wenn das Objekt Y auf dem Stack liegt.

    Bsp:

    class X {};
    
    class Y
    {
    ...
    privat:
       vector<X> m_X;
    };
    
    void somefunc()
    {
       Y y;
    }
    

    y liegt hier auf dem Stack, das Objekt m_X auch - aber die Inhalte von m_X, die ganzen X-Objekte, sind auf dem Heap.

    Das kann auch nicht funktionieren, weil der Stack etwas relativ simples ist (daher ist er ja auch schnell - dafür unflexibel). Beim Eintritt in eine Funktion ist vom Compiler festgelegt worden, wieviele Bytes Speicher diese Funktion auf dem Stack benötigt. Diese Anzahl wird einfach auf den Stackpointer addiert (oder abgezogen, je nach System). Erst danach wird die Bearbeitung der Funktion begonnen, bzw. die Konstruktoren aufgerufen. Wenn Du nun also erst die Anzahl feststellst, ist es bereits zu spät hier etwas am Stack zu manipulieren.

    Die Frage ist aber, warum Du ein Problem mit dem Heap hast? Willst Du viele sehr kleine Objekte speichern und machst Dir Sorgen wegen des langsamen Zugriffs? Dann verwende doch eine andere dynamische Struktur... z.B. einen vector oder eine deque, die allokieren im Gegensatz zur Liste nicht für jedes Objekt Speicher, sondern immer gleich für n Objekte auf einmal.



  • Original erstellt von Marc++us:
    Das geht nicht.

    Bevor irgendein Naseweis hier was reinstreut: ich könnte mir ein paar dirty Hacks vorstellen, wie man das erreichen kann... aber nichts davon gefällt mir so, daß ich es hier posten würde.



  • Für VC++

    _alloca
    Allocates memory on the stack.



  • 😞 Also komm ich um den Heap nicht drumrum.

    wegen des langsamen Zugriffs

    genau das ist der Punkt. Hatte die Hoffnung auf diese Weise meinen Programmablauf zu beschleunigen. Was meint ihr, ist es sinnvoll im Stack Platz für Objekte zu reservieren und bei Bedarf diese aus dem Heap in den Stack zu laden um dann dort damit zu arbeiten?



  • wegen des langsamen Zugriffs

    1. Wer sagt, dass Zugriffe auf den Heap langsam sind? Beim ersten Zugriff wird der Speicherblock in den Prozessorcache gelegt und damit sind die Zugriffe schnell.
    2. Bei Zugriff auf eine Stackvariable muss er jedesmal [esp+offsetVariable] rechnen, also wenn Dein Zeiger direkt auf die Variable zeigt, ist Zugriff auf Heap sogar schneller.



  • hat dir dein profiler gesagt dass dein programm deswegen langsam ist?

    Wenn nicht, dann lass es sein und mach keine dirty hacks.

    Objekte am Heap sind nur ganz wenig langsamer (es muss eben eine indirektion durchgefuehrt werden) -> dein programm koennte man sicher viel schneller machen, wenn man bessere algorithmen und datenstrukturen nimmt, oder indem man die temporaeren variablen eleminiert,...

    das was du machen willst, sollte man nur dann machen wenn man es wirklich machen _muss_, sonst ist es bloedsinn.



  • Was Du wahrscheinlich meinst ist, dass viele new's und delete's langsam sind. Aber wenn der Speicher erst mal angelegt wurde, ist er genau so schnell. Deshalb ist es unter Umständen ratsam, auf die vielen new's und delete's zu verzichten, wenn es irgend wie nur geht. Soll heissen, dass man zwar Speicher braucht, aber bevor man ihn wieder freigibt und später wieder anfordert, sollte man ihn besser gleich behalten. Ich habe mal ein Programm geschrieben, was auch wegen vielen new's und delete's sehr langsam war. Anschliessend habe ich mir eine eigene Speicherverwaltung geschrieben, die ich für diese relevanten Objekte verwendet habe. Meine Erfahrung dabei war, dass "Buddy-Systeme" zwar nicht sehr effizient sind, was die optimale Aufteilung des Speichers angeht, aber dafür sehr effizient. Der Unterschied war nachher zu spüren!



  • Gut, ich probiere mal die Lösung mit der eigenen Speicherverwaltung zur Vermeidung von unnötigen Reservierungen und Freigaben.

    Original erstellt von RenéG:
    in den Prozessorcache gelegt

    Der Cache hilft bei dem Problem glaub ich nicht viel weiter. Denn der schnelle Zugriff aus dem Cache gilt ja sowohl für den Stack als auch für den Heap.

    Original erstellt von Shade of mine:
    a)hat dir dein profiler gesagt
    b)bessere algorithmen ... variablen eleminiert
    c)machen _muss_

    zu a) 😕 profiler 😕
    zu b) über den Punkt bin ich schon hinaus. allerdings hatte ich noch nicht an
    die temporären Variablen gedacht
    zu c) aus äußerem Zwang heraus oder gibt es tatsächlich rein programmtechnisch Situationen die eine solche Maßnahme verlangen?



  • Original erstellt von Sprotti:
    zu a) 😕 profiler 😕

    ein profiler ist ein programm welches die genaue laufzeit jeder funktion deines programmes analysiert.
    Auf deutsch gesagt: ein profiler sagt dir, wo dein programm zu langsam ist

    zu b) über den Punkt bin ich schon hinaus. allerdings hatte ich noch nicht an
    die temporären Variablen gedacht

    tja, ohne profiler ist das keine lohnende arbeit. bedenkte die 80-20 regel
    (80% der laufzeit werden von 20% deines codes erzeugt - wenn du an der falschen stelle optimierst, bringt das also garnix)

    zu c) aus äußerem Zwang heraus oder gibt es tatsächlich rein programmtechnisch Situationen die eine solche Maßnahme verlangen?

    ja, wenn du zu dem schluss gekommen bist, dass new zu langsam ist fuer deine verhaeltnisse (aber das duerfte theoretisch nicht passieren - da wuerde ich eher noch speicher pools angelgen, etc.)

    mein Tipp:
    schnapp dir einen profiler (google mal danach) und schau dir an wo dein programm langsam ist. dort kannst du dann optimieren. aber so aus dem bauch heraus bringt nicht viel, denn meistens schaetzt man die laufzeit falsch ein.



  • Ich will noch mal daran erinnern, daß z.B. vector oder deque bereits solche Speicherpools darstellen! Macht man ein vector<T>.push_back(T& t), so wird für das neue Objekt kein neuer Speicher im Heap allokiert, es fällt also kein zusätzliches new an. Dies passiert erst, wenn die Grundanzahl an Objekten nicht mehr ausreicht und ein ganz neues Array angelegt werden muß.

    Alternativ wäre dafür noch eine deque<T> interessant.



  • thx@all of u



  • Weg damit.

    [ Dieser Beitrag wurde am 26.06.2003 um 12:31 Uhr von Lars editiert. ]



  • [ Dieser Beitrag wurde am 26.06.2003 um 12:31 Uhr von Lars editiert. ]



  • Original erstellt von RenéG:
    **Für VC++
    _alloca
    Allocates memory on the stack.
    **

    MSDN:

    The allocated space is automatically freed when the calling function exits.

    char string[20];
    char* pStr = &string;
    

    ist also im Prinzip das selbe wie

    char* pStr = _alloca(20);
    

    [ Dieser Beitrag wurde am 26.06.2003 um 12:29 Uhr von MaSTaH editiert. ]



  • ...

    [ Dieser Beitrag wurde am 26.06.2003 um 12:31 Uhr von Lars editiert. ]



  • Original erstellt von MaSTaH:
    *```cpp
    char string[20];
    char
    pStr = &string;

    
      
    ist also im Prinzip das selbe wie  
    
    ```cpp
    char* pStr = _alloca(20);
    ```**
    

    Im prinzip, aber was ist mit

    void foo(char const* str, int length)
    {
      char* t=_alloca(length);
      strcpy(t,str);
      do_something(t);
    }
    

    im prinzip ist _alloca ein moeglichkeit VLAs zu erzeugen 🙂


Anmelden zum Antworten