Anwendbarkeit von C-Funktionen auf Klassen



  • ⚠ Vorsicht ! Der folgenden Quellcode ist eine feine Mischung aus C und C++ und könnte bei so manchen zu einem Wutanfall führen. ⚠

    Könnte bei folgendem Quellecode ein Problem auftauchen ? Ich habe es erfolgreich getestet, jedoch ist es für mich nix anderes als ein Hack.

    class tArrayNode
    {
    public:
      int a;
      int b;
    
    public:
      tArrayNode();
      int GetSum();
    }
    
    tArrayNode::tArrayNode()
    {
      this->a = 0;
      this->b = 0; 
    }
    
    int tArrayNode::GetSum()
    {
      return a + b;
    }
    
    int CompareArrayNode(const void* a, const void* b)
    {
      tArrayNode* node_a = (tArrayNode*) a;
      tArrayNode* node_b = (tArrayNode*) b;
    
      return node_a->a < node_b->a;
    }
    
    int main(int argc, char** argv)
    {
      tArrayNode array[5];
    
      // Initialisierung des Arrays
      array[0] = tArrayNode();
      array[1] = tArrayNode();  
      array[2] = tArrayNode();
      array[3] = tArrayNode();  
      array[4] = tArrayNode();
      // Aufruf des Quicksorts auf einer Liste von Objekten
      qsort(array, 5, sizeof(tArrayNode), CompareArrayNode);
      return 0;
    }
    

    Eine Frage leidet sich daraus schnell hervor. Wie funktioniert hier das vertauschen zweier Objekte? Da man beim Aufruf von qsort() die Größe eines Elements angeben muss, schätze ich mal dass die Elemente mittels memcpy() verschoben werden. Und daraus stellt sich mir halt auch die Frage ob man überhaupt Objekte mittels memcpy() verschieben (nicht kopieren) darf.

    Und wie macht überhaupt dies eine Liste (std::vector) aus der STL ? Wie werden Listenelemente in der STL verschoben. Einen speraten Kopierkonstruktor, oder einen Kopieroperator, sind nämlich nicht zwingend erforderlich.



  • Informier Dich mal zum Stichwort POD. Da Dein Typ ein POD ist, sollte es keine Probleme geben.

    Ich frage mich aber, wieso Du überhaupt 'qsort' verwendest und nicht einfach 'sort'.


  • Mod

    Bitte ein Bit schrieb:

    Eine Frage leidet sich daraus schnell hervor. Wie funktioniert hier das vertauschen zweier Objekte? Da man beim Aufruf von qsort() die Größe eines Elements angeben muss, schätze ich mal dass die Elemente mittels memcpy() verschoben werden. Und daraus stellt sich mir halt auch die Frage ob man überhaupt Objekte mittels memcpy() verschieben (nicht kopieren) darf.

    Wenn es sich um PODs handelt. tArrayNode ist kein POD (Konstruktor selbst definiert), somit hast du hier undefiniertes Verhalten.

    Und wie macht überhaupt dies eine Liste (std::vector) aus der STL ? Wie werden Listenelemente in der STL verschoben. Einen speraten Kopierkonstruktor, oder einen Kopieroperator, sind nämlich nicht zwingend erforderlich.

    Jede Klasse hat einen Kopierkonstruktor. Damit eine Klasse als Element eines Containers benutzt werden kann, muss diese Klasse über eine bestimmte Kopiersemantik verfügen, andernfalls resultiert ebenfalls undefiniertes Verhalten.



  • camper schrieb:

    tArrayNode ist kein POD (Konstruktor selbst definiert)

    Arg, den hatte ich übersehen. 😕

    /EDIT: Das zeigt vielleicht, wie gefährlich es ist, sich auf sowas zu verlassen. 😉



  • Danke,

    jetzt weis ich was POD Objekte sind. Ich werde dann wohl oder übel qsort ersetzen müssen.



  • Bitte ein Bit schrieb:

    jetzt weis ich was POD Objekte sind. Ich werde dann wohl oder übel qsort ersetzen müssen.

    Hm, ich weiß trotzdem nicht, was daran so schlimm ist. 'sort' ist sowieso effizienter.



  • Warum ist 'sort' effizienter als qsort ?

    Denn der qsort ist meines Erachtens der schnellste Sortieralgorithmus. Schneller sind nur noch Sortieralgorithmen die nicht auf Elementvergleiche basieren. Ein randomisierter Quicksort hat im durchschnittlichen Fall eine Laufzeit von n*log(n).



  • Bitte ein Bit schrieb:

    Warum ist 'sort' effizienter als qsort ?

    Zwei Gründe.

    Erstens implementiert 'qsort' ein Quicksort, 'sort' hingegen in modernen Implementierungen ein Introsort, welches dieselbe Average-Case-Laufzeit besitzt, aber einen verbesserten Worst Case; und das, ohne ein signifikantes zusätzliches Overhead.

    Zweitens ist 'sort' streng typisiert und kann daher die Vergleichsoperation inlinen, wenn sie als Funktor implementiert ist. 'qsort' kann das nicht, sondern muss einen Funktionszeiger aufrufen, was teurer ist.

    Ein randomisierter Quicksort hat im durchschnittlichen Fall eine Laufzeit von n*log(n).

    Den hat ein nicht-randomisierter auch. 😉 Die randomisierte Variante macht nur den Worst-Case (wesentlich) unwahrscheinlicher.



  • Danke für die Info.

    Da ich den Intro-Sort nicht kenne, werde ich ihn mir wohl noch ansehen.



  • Bitte ein Bit schrieb:

    Da ich den Intro-Sort nicht kenne, werde ich ihn mir wohl noch ansehen.

    Das ist im wesentlichen dasselbe wie ein Quicksort, allerdings mit einer eingebauten Heuristik, die bestimmen soll, ob für den aktuellen Sortierschritt ein Quicksort überhaupt angebracht ist, oder ob es nicht schneller wäre, stattdessen auf andere Verfahren (meist Heapsort) auszuweichen. Das ist z.B. dann der Fall, wenn nur wenige Elemente übrig sind, oder wenn drei gezielt gewählte Elemente aus der zu sortierenden Sequenz sich bereits in der korrekten Reihenfolge befinden (QuickSorts Worst-Case ist eine bereits sortierte Sequenz).


Anmelden zum Antworten