Hidden && Opaque && Smart Pointer in C/C++



  • Hallo,

    ich wollte einmal nachfragen was diese Pointer jeweils in C und in C++ ausmacht, welche Eigenschaften sie haben, welches es überhaupt gibt und wann und wie man sie benutzt.

    Vielen Dank im Voraus.

    MfG
    Komisch



  • Ist dasselbe wie in Java, nur klarer aus der Sprache herausgearbeitet, so dass es quasi nicht versteckt wird.

    Alles was in Java per new erzeugt wird/werden muss, ist ein sogenannter Referenzvariabloen-Datentyp. Im Grunde also ein Zeiger auf einen Speicherplatz wo ein Objekt "lebt". Und dieser Zeiger kann im Zweifel auch mal leer sein, sprich null.

    Foo f = new Foo("MyObj");
    

    In C++ werden Objekte erstmal nicht per new angelegt, sodnern wie gewöhnliche Standard-Datentypen auch:

    Foo f("MyObj");
    

    Aber das kann manchmal eine Einschränkung sein, dass so quasi nur ein Call-by-Value überall möglich wäre.
    Deswegen gibt es zusätzlich auch noch normale Zeiger (wie in Java) (die auch ungültig, also auf 0/null/NULL/nullptr zeigen können):

    Foo * f = new Foo("MyObj");
    delete f;
    

    So, da da aber Speicher angelegt wird, muss dieser auch wieder freigegeben werden mit einem delete. In Java macht das der Grabage Collector.
    Da man das so wie in meinem zweizeiligen Beispiel aber total fehleranfällig ist (man vergesse z.b. delete) macht man das seit etwa 20-30 Jahren nicht mehr so, sondern nutzt Smart-Pointer (z.b. std::unique_ptr). Die Folge ist, dass Anwendung nicht alle paar Sekunden mal kurz ruckelt, weil da ein Magic GC irgendwas aufräumen muss.

    Das was dann viele Leute sehr verwirrt sind Referenzen, das sind technisch gesehen auch Zeiger, die aber durch den Compiler forciert niemals auf null zeigen können.

    Kleine Geschichte am Rande:
    Ich hatte in meinem Leben bisher nur 2-3 kleine Probleme was die Speicherverwaltung in C++ anging, d.h. Memory Leak oder so. Das passiert in Java natürlich so nicht.
    Aber wenn du in Java Speicherprobleme kriegst, dann richtig und dann ist das richtig viel Arbeit da was gegen zu amchen und die Ursachen rauszufinden. Kurzum, ich hab bisher mit dem Speichermanagement in Java mehr und größere Probleme gehabt als in C++.
    Und die Speicherverwaltung war immer das Argument gegen C++ (angeblich).



  • Naja in Java gibt es ja verschiedene Referenzen um mit Speicherproblemen umzugehen und den GC etwas zu lenken (Soft, Weak, (Phantom) Referenzen)
    Allerdings hätte mich jetzt mehr interessiert was man in C/C++ für Pointertypen antreffen kann und wie sie sich verhalten...

    Skym0sh0 schrieb:

    In C++ werden Objekte erstmal nicht per new angelegt, sondern wie gewöhnliche Standard-Datentypen auch:

    Foo f("MyObj");
    

    Aber das kann manchmal eine Einschränkung sein, dass so quasi nur ein Call-by-Value überall möglich wäre.

    Die Initialisierung auf diese Weise verursacht doch eigl. nur, dass das Objekt nur für den Abarbeitungszeitraum des Prozesses lokal im Adressraum und dort im Stacksegment dieses Prozesses angelegt wird (da kurzlebig). Ansonsten dürfte es doch einen ganz normalen Pointer(gerne hier spezifizieren was ganz normal ist :D) auf das Objekt geben.

    Foo * f = new Foo("MyObj");
    delete f;
    

    Hier wird explizit auf dem Heap speicher reserviert und das Objekt existiert so lange bis der reservierte Speicher wieder freigegeben wurde.

    Nun gibt es aber auch smart_pointer welche zählen wie viele Verweise auf ein Objekt existieren (gibt es unterschiedliche Arten von Smart_pointern?) (würde mich hier über eine detailierte Erklärung freuen was wann wie gezählt wird und wann dekrementiert und wann inkrementiert wird etc.)

    Welche Anderen Arten von Pointern existieren noch?...



  • Komisch schrieb:

    Naja in Java gibt es ja verschiedene Referenzen um mit Speicherproblemen umzugehen und den GC etwas zu lenken (Soft, Weak, (Phantom) Referenzen)
    Welche Anderen Arten von Pointern existieren noch?...

    Weak_ptr hast du in C++ auch.
    Nur brauchst du das in C++ so gut wie nie. In Java hast du halt keine raw-Pointer, was dich dazu zwingt. In C++ zum Glück nicht.
    Da sollte das eher so aussehen, dass z.B. eine Klasse ein Objekt besitzt (= unique_ptr) und Unterklassen (im Sinne von kürzer lebend) oder Funktionen mit raw-Pointern arbeiten, die sie sich von der Ober-Klasse holen.
    Man muss sich in C++ um 'Besitz' (owning) von Objekten etwas mehr kümmern, was ich aber eigentlich als Vorteil sehe.

    (würde mich hier über eine detailierte Erklärung freuen was wann wie gezählt wird und wann dekrementiert und wann inkrementiert wird etc.)

    Ist das nicht offensichtlich? Im Destruktor wird dekremtiert und beim Erstellen einer (weiteren) Instanz oder Zuweisung wird inkrementiert.



  • Also offiziell gibt es;
    - Raw Pointer
    - Auto Pointer (Deprecated und nicht nutzen!)
    - unique_ptr
    - shared_ptr
    - weak_ptr

    Eventuell könnte man noch den boost::ptr_vector (oder so heisst der) dazu zählen



  • Wenn man auch bei Boost guckt darf man boost::intrusive_ptr mMn. nicht vergessen. Ist zwar vergleichsweise trivial zu implementieren, aber wenn richtig eingesetzt ne gute Sache. boost::intrusive_ptr wird mMn. viel zu oft übersehen.


Anmelden zum Antworten