std::stack / Wieso keine clear Methode?



  • Werner Salomon schrieb:

    Naja - ich will eben nicht das selbe verwenden. Wenn ich die von Dir beschriebene Aufgabe ausführen will, zu der ich den Stack benötige, dann beginne ich mit einem 'frischen' Stack-Objekt. Damit habe ich garantiert gleiche Startbedingungen und habe sicher keine Seiteneffekte von vorherigen Durchläufen. Ich habe schon das eine oder andere Mal Fehler aus Programmen rausmachen können, wo genau so etwas passiert ist.

    Sind die STL-Container derart verbuggt, dass man lieber Destruktor und Konstruktor aufrufen will anstatt die clear() -Funktion zu benutzen? Klar wird der Speicher z.B. bei std::vector<> nicht mehr freigegeben, aber das wurde wohl eher aus dem Grund gemacht, dass der Vektor mit einer grossen Wahrscheinlichkeit wieder gefüllt wird und man sich so die Reallokation des internen Arrays sparen kann...

    Werner Salomon schrieb:

    Laut Standard ist der Container als Member im std::stack protected und heißt immer 'c'. Man kann sich also leicht die gewünschte Add-In-Funktionalität selber basteln:
    [...]

    Naja, ob sich das lohnt... 🙄
    Da macht man doch lieber die Funktion mit der While-Schleife und pop() .



  • Nexus schrieb:

    Naja, ob sich das lohnt... 🙄
    Da macht man doch lieber die Funktion mit der While-Schleife und pop() .

    > die Clearmethode aufrufen ist vermutlich wesentlich performanter^^



  • Rissender schrieb:

    Nexus schrieb:

    Naja, ob sich das lohnt... 🙄
    Da macht man doch lieber die Funktion mit der While-Schleife und pop() .

    > die Clearmethode aufrufen ist vermutlich wesentlich performanter^^

    Nur schade, dass sie nicht existiert.



  • Dravere schrieb:

    Mr Evil schrieb:

    #InDenRaumWerf

    Immer diese Leute mit den Präprozessor anweisungen. 🙂

    durch diese direktive ist eine glaubwuerdigkeit nicht gewaehrleistet #gg

    Dravere schrieb:

    Mr Evil schrieb:

    - alles was in einem stack gepackt wird soll auch wieder heraus genommen werden

    Ist bei einem clear gewährleistet.

    ich meinte eher so "rausnehmen und benutzen" nicht nur wegwerfen

    Dravere schrieb:

    Mr Evil schrieb:

    - neue aufgaben = neuen stack

    Wieso kann man das gleiche Objekt nicht wiederverwenden? Wird doch oft auch getan und erscheint auch sinnvoll zu sein.

    Mr Evil schrieb:

    - stack leeren bedeutet aufgaben verwerfen und einen neuen stack starten - da sollte gleich ein neuer stack gebaut werden

    Und wieso gleich einen neuen? Wozu der Unterschied? Wieso der zusätzliche Aufwand? Wieso nicht gleich das gleiche Objekt wiederverwenden? Das macht doch überhaupt gar keinen Sinn.

    Weiss ich doch nicht {o; war wie gesagt nur ne idee das es so gedacht sein kann #gg
    so ala
    "wer ein stack braucht der braucht immer nur eines pro aufgabe, amsonsten ist die liste zu verwenden"

    irgenwas muessen die sich ja dabei gedacht haben soetwas grundlegendes wie clear fuer den einen container nicht zu implementieren

    vieleicht auch
    "so wenig funktionen wie moeglich um die klasse stack klein zu halten"
    "wenn wir dann "clear" implementieren muessten wir auch noch .. und .. sowie .. und .. implementieren, da wirds dann zu gross"
    "stack soll ne kleine aufgabenliste bleiben"

    ich pers. hatte den stack mal fuer n kartenstapel verwendet und mich dann so richtig gewundert das das clear "auf einmal" gar nicht zur verfuegung stellt #gg



  • Nexus schrieb:

    Rissender schrieb:

    Nexus schrieb:

    Naja, ob sich das lohnt... 🙄
    Da macht man doch lieber die Funktion mit der While-Schleife und pop() .

    > die Clearmethode aufrufen ist vermutlich wesentlich performanter^^

    Nur schade, dass sie nicht existiert.

    Wie man's nimmt, wie Simon2 gesagt hat, gehört ein Clear nicht zu dem, was ein Stack als Konzept per Definition benötigt.
    Wenn dann also ein Workaround nehmen, wie das "stack_mit_clear"-template



  • Nexus schrieb:

    Da macht man doch lieber die Funktion mit der While-Schleife und pop() .

    ich wuerd erher den stack mit einem neuen leeren ueberschreiben "oldStack = std::stack<object>();"
    wird denk ich performanter sein als das blanke loopen mit pop



  • Rissender schrieb:

    Wie man's nimmt, wie Simon2 gesagt hat, gehört ein Clear nicht zu dem, was ein Stack als Konzept per Definition benötigt.
    Wenn dann also ein Workaround nehmen, wie das "stack_mit_clear"-template

    Okay, ich dachte, du meintest das nicht existierende std::stack::clear() .
    Aber beim Workaround kommt wieder das Problem mit Vererbung von STL-Containern. Und ausserdem finde ich das auch nicht eine sehr schöne Lösung (eben ein Workaround).

    Mr Evil schrieb:

    Nexus schrieb:

    Da macht man doch lieber die Funktion mit der While-Schleife und pop() .

    ich wuerd erher den stack mit einem neuen leeren ueberschreiben "oldStack = std::stack<object>();"
    wird denk ich performanter sein als das blanke loopen mit pop

    Das ist schon möglich, ich weiss jetzt nicht, was da intern genau passiert beim Aufruf des Zuweisungsoperators.


  • Administrator

    Mr Evil schrieb:

    ich meinte eher so "rausnehmen und benutzen" nicht nur wegwerfen

    Wegwerfen ist auch ein benutzen. Die dürfen mir doch nicht vorschreiben, was ich mit den Objekten mache, welche ich auf den Stack ablege :p

    Zum Rest deines Postings, sage ich jetzt nichts weiteres mehr und hoffe einfach, dass die sich wirklich etwas dabei gedacht haben. Sonst bekommen sie etwas von mir zu hören 😃

    @Nexus,
    Genau, dieses Schade finde ich auch. Und deswegen frage ich nun bereits über x Seiten, was die sich denn dabei gedacht haben, sowas nicht reinzunehmen?

    @Rissender,
    Oder man nimmt ein std::list oder ein std::deque und hat eigentlich auch einen Stack, wenn man sie entsprechend verwendet. Allerdings gleich automatisch noch ein clear.

    Grüssli



  • Dravere schrieb:

    Werner Salomon schrieb:

    Naja - ich will eben nicht das selbe verwenden. Wenn ich die von Dir beschriebene Aufgabe ausführen will, zu der ich den Stack benötige, dann beginne ich mit einem 'frischen' Stack-Objekt. Damit habe ich garantiert gleiche Startbedingungen und habe sicher keine Seiteneffekte von vorherigen Durchläufen. Ich habe schon das eine oder andere Mal Fehler aus Programmen rausmachen können, wo genau so etwas passiert ist.

    Kann man das auch so interpretieren, dass du deinem Computer, bzw. der Bibliothek nicht vertraust?

    .. muss man aber nicht. Worauf ich nicht vertraue ist, dass Leute die nach Monaten oder Jahren Code von anderen Leuten ändern, diesen 100% durchschauen. Ja ich gehe davon aus, dass sie es nicht tun.

    Man betrachte folgenden Code (Skizze):

    std::stack< MeineKlasse > st;
    for( ... )
    {
        // Start der Aufgabe .. st muss hier leer sein
        ... // 100 Zeilen 
        clear( st ); // leert 'st', denn oben muss 'st' wieder leer sein.
    }
    

    2 Jahre später, nach vielen Weiterentwicklungen, macht jemand eine Änderung:

    std::stack< MeineKlasse > st;
    for( ... )
    {
        // Start der Aufgabe .. st muss hier leer sein
        ... // 70 Zeilen 
       if( /* die Aufgabe ist schon erledigt */ )
           continue;
        ... // 80 Zeilen 
        clear( st ); // leert 'st', denn oben muss 'st' wieder leer sein.
    }
    

    Fällt bei den ersten Tests nicht auf, da am Ende der Aufgabe der Stack normalerweise immer leer sein muss. Erst nach zwei weiteren Änderungen passiert es ... und dann finde mal den Fehler!

    Jetzt kommt jemand auf die Idee, das clear() oben in die Schleife zu stellen. Dann kommt Monate später der Performance-Junkie und macht das wieder weg, weil er meint, nach dem Konstruktor-Aufruf ist das wohl überflüssig. Haben wir alles schon gehabt.

    Gruß
    Werner


  • Administrator

    Werner Salomon schrieb:

    Jetzt kommt jemand auf die Idee, das clear() oben in die Schleife zu stellen.

    Genau.

    Werner Salomon schrieb:

    Dann kommt Monate später der Performance-Junkie und macht das wieder weg, weil er meint, nach dem Konstruktor-Aufruf ist das wohl überflüssig. Haben wir alles schon gehabt.

    Darf ich wetten, dass dieser Voll-Idiot aber auch folgendes abändern würde:

    for(;;)
    {
        std::stack<Irgendwas> Stack;
        // ...
    }
    

    So, dass das Objekt vor dem for(;; ) erstellt wird? Tut mir ja leid, aber gegen Dummheit kann wirklich nichts helfen. Da benutze ich lieber die Bibliothek so, wie sie zu verwenden ist. Wenn ein Idiot daherkommt, hilft nichts mehr.

    Grüssli



  • Dravere schrieb:

    Werner Salomon schrieb:

    Dann kommt Monate später der Performance-Junkie und macht das wieder weg, weil er meint, nach dem Konstruktor-Aufruf ist das wohl überflüssig. Haben wir alles schon gehabt.

    Darf ich wetten, dass dieser Voll-Idiot aber auch folgendes abändern würde:

    for(;;)
    {
        std::stack<Irgendwas> Stack;
        // ...
    }
    

    So, dass das Objekt vor dem for(;; ) erstellt wird?

    nun - ich habe zumindest noch keinen dabei erwischt. Wohingegen die erste Geschichte mit dem if() continue; mehr als einmal vorgekommen ist. Und in diesen Fällen wäre das lokale Stack-Objekt innerhalb der for-Schleife der bessere Code gewesen.

    Gruß
    Werner



  • Werner Salomon schrieb:

    Dravere schrieb:

    Werner Salomon schrieb:

    Dann kommt Monate später der Performance-Junkie und macht das wieder weg, weil er meint, nach dem Konstruktor-Aufruf ist das wohl überflüssig. Haben wir alles schon gehabt.

    Darf ich wetten, dass dieser Voll-Idiot aber auch folgendes abändern würde:

    for(;;)
    {
        std::stack<Irgendwas> Stack;
        // ...
    }
    

    So, dass das Objekt vor dem for(;; ) erstellt wird?

    nun - ich habe zumindest noch keinen dabei erwischt. Wohingegen die erste Geschichte mit dem if() continue; mehr als einmal vorgekommen ist. Und in diesen Fällen wäre das lokale Stack-Objekt innerhalb der for-Schleife der bessere Code gewesen.

    Gruß
    Werner

    Dann ist sowas aber noch schöner:

    struct stack_auto_ptr
    {
    	stack_auto_ptr( std::stack< int > &s ) : m_s( s ){}
    
    	~stack_auto_ptr()
    	{
    		// und genau hier wäre jetzt das clear schön
    		m_s = std::stack< int >();
    
    		m_s.c.clear(); // oder halt so
    	}
    
    private:
    	std::stack< int > &m_s;
    };
    
    ...
    
    std::stack< int > steck;
    
    for(;;)
    {
    	stack_auto_ptr as( steck );
    
    // 500000 Zeilen mit break, continue und schlag mich tot
    }
    

    Packste das ganze noch in ein Template und alle sind glücklich ( bis auf die die ein clear wollen 😛 )



  • rean schrieb:

    [...]
    Packste das ganze noch in ein Template und alle sind glücklich ( bis auf die die ein clear wollen 😛 )

    Schön, wie immer wieder Möglichkeiten gefunden werden, einfachen Code unnötig kompliziert zu machen. Aber ganz idiotensicher wird der Code sowieso nie sein, von daher...
    Wenn sich Mitarbeiter besser achten und den Code wirklich verstehen würden, wären wohl wirklich viele glücklich 😉


Anmelden zum Antworten