2 Fragen zur STL::list



  • Hallo!

    Hier die zwei Fragen:

    1.)
    Wenn ich in einer STL-list etwas finden möchte ist es ja möglich eine Funktion zu übergeben, nur ich hab das noch nie gemacht, wie funktioniert das Prinzip dahinter bzw. kann man überhaupt eine Funktion (oder einen Pointer auf eine Funktion?) übergeben?

    2.)
    Die list hat ja eine sort()-Methode, diese wollte ich nachbilden. Praktisch gibt es da nur leider ein Problem:

    Man kann ja eine Liste erstellen wo die Adressen von Objekten gespeichert werden oder eine Liste wo direkt Kopien von Instanzen gespeichert werden, je nachdem ob man

    list<object*> foo; // Adressen
    

    oder

    list<object> foo; // Kopien der Instanzen
    

    macht.

    Da gibt es nämlich ein Problem mit dieser Zeile:

    if((*temp->element) > (*temp->next->element))
    

    Hier wurden Adressen gespeichert und um an die Methoden / Attribute ranzukommmen muss noch einmal derefenziert werden.
    Werden jetzt allerdings Instanzen gespeichert funktioniert diese sort()-methode natürlich nicht mehr 😞 .

    Ich weiß nicht wie ich das umgehen kann? Lässt sich irgendwie rausfinden was gespeichert wurde? 😕 Überladen geht ja nicht, da die Methode keinen Rückgabewert und keine Parameter hat.



  • Iteratoren sind das Geheimnis.

    zu 1. nimm std::find aus <algorithm>



  • Wie bringen mich Iteratoren da weiter? Wenn ich in einer Liste Adressen von Objekten Speicher muss ich ja auch, wenn ich darauf zugreifen möchte, dereferenzieren.

    Da hätte ich genau das gleiche Problem.

    Ich hab die Methode schon einfach kopiert und aus dem Rückgabewert statt void bool gemacht, in der Hoffnung der Compiler könnte das unterscheiden -> leider nicht 😞 😞

    Und ich darf / will nichts von der STL verwenden, ich muss das alles selber Coden.
    Wer gibt mir da noch einen Ansatz für eine Find()-Methode? Wie funktioniert das das ich eine Funktion übergebe und die Methode dann mit der Übergebenen arbeitet?!



  • zu 1.) Es werden Prädikate benützt. Das ist ein Funktionsobjekt das als Rückgabewert bool hat. Ein Funktionsobjekt ist sowas:

    struct iseven
    {
        bool operator() (int a)
        {
           return a%2==0;
        }
    };
    

    Das ist hier jetzt auch gleihczeitig ein Prädikat weils bool zurückgibt. Damit das auch STL-konform wird und überall eingesetzt werden kann gibts Templates die benützt werden sollen:

    template <class T>
    struct isodd : public unary_function<Typ,bool>
    {
        bool operator() (T a) { return a%2==0; }
    };
    

    So ein Prädikat kann dann an STL-Funktionen übergeben werden, zB auch remove_if:

    remove_if(a,b,isodd<int>());
    

    Es wird hier als Parameter 3 ein neues isodd<int> erstellt, die zwei Klammern dahinter rufen den Konstruktor auf. Und remove_if ruft einfach immer den op() auf, den hat isodd weil geerbt von unary_function.

    Es gibt bereits ein paar vordefinierte Prädikate in der <functional>, musst mal schauen.

    Zu 2.) Nein du vergleichst grundsätzlich Instanzen und Pointer werden anhand ihrer Adresse sortiert. Kannst aber auch hier std::sort benützen und ein Prädikat für einen Pointertyp bauen.

    MfG SideWinder



  • vielleich hilft dir das weiter
    http://www.function-pointer.org/
    K.



  • Funktionspointer werden in der STL imho nicht benützt.

    MfG SideWinder



  • es gibt da auch ein kapitel über functors.
    K.



  • SideWinder schrieb:

    zu 1.) Es werden Prädikate benützt. Das ist ein Funktionsobjekt das als Rückgabewert bool hat. Ein Funktionsobjekt ist sowas:

    struct iseven
    {
        bool operator() (int a)
        {
           return a%2==0;
        }
    };
    

    Das ist hier jetzt auch gleihczeitig ein Prädikat weils bool zurückgibt. Damit das auch STL-konform wird und überall eingesetzt werden kann gibts Templates die benützt werden sollen:

    template <class T>
    struct isodd : public unary_function<Typ,bool>
    {
        bool operator() (T a) { return a%2==0; }
    };
    

    So ein Prädikat kann dann an STL-Funktionen übergeben werden, zB auch remove_if:

    remove_if(a,b,isodd<int>());
    

    Es wird hier als Parameter 3 ein neues isodd<int> erstellt, die zwei Klammern dahinter rufen den Konstruktor auf. Und remove_if ruft einfach immer den op() auf, den hat isodd weil geerbt von unary_function.

    [...]

    So, heute kann ich weitermachen, leider muss ich zugeben das ich die Funktionsweise immer noch nicht ganz kapiert habe:

    Angenommen in der Liste werden Personen gespeichert und nun möchte ich den ersten Eintrag finden, dessen Vorname Hans ist.

    Wenn man das jetzt nicht dynamisch machen würde sähe das ganze so aus

    Person List::Find(string v)
    	{
    		for(int i=0; i<Size(); ++i)
    			if(element->Vorname == v)
    				return(element);
    			else
    				element = element->GoNext();
    	}
    

    Ganz grob umrissen. Jetzt kann ich leider das was du mir erzählt hast nicht darauf übertragen, könntest du evt. ein Codebeispiel geben, dafür wäre ich dir echt dankbar. 😋


Anmelden zum Antworten