Zeiger vs. Referenzen



  • Hast du vielleicht einen Beispiel, bei dem man Zeiger benutzen muß, ohne daß man das selbe auch mit Referenzen erreichen kann?

    Ja, klar, greif mal auf ein Array zu.
    (Egal wie du das machst werden immer Zeiger im Spiel sein, auch wenn man im Code keine "sieht")



  • Hmmm... schrieb:

    Verkettete Listen sind IMHO auch ohne Zeiger möglich.

    Das möchte ich gerne sehen 😉



  • Hmmm... schrieb:

    Verkettete Listen sind IMHO auch ohne Zeiger möglich.

    Das wird sicher einige hier interessieren, wie du eine Verkettete Liste (am Betsen eine double linked list) in C++ ohne Zeiger implementieren willst. Hast du dazu ein Beispiel oder einen Link auf Lager?



  • Hmmm... schrieb:

    CStoll schrieb:

    optionale Werte - du übergibst NULL für "der Wert interessiert mich nicht"

    Man könnte doch eine Referenz auf einen Wert "interessiert mich nicht" übergeben.

    Und wie soll der Wert aussehen? Hinter einer Referenz steht IMMER eine existierende Variable, ein Zeiger kann auf NULL verweisen.

    CStoll schrieb:

    Sondermarkierungen, z.B. für das Ende einer verketteten Liste
    wo wir gerade bei Listen sind: Die Nachfolger-Beziehungen zwischen Elementen können/müssen sich während der Laufzeit auch ändern

    Verkettete Listen sind IMHO auch ohne Zeiger möglich.

    Dann zeig doch mal, wie du DAS anstellen willst.


  • Mod

    Wenn man brutal genug vorgeht, kann man auch Zeiger mit Referenzen implementieren (keine NULL-Pointer in diesem Fall, aber die braucht man nicht unbedingt), ohne Arithmetik, aber die braucht man ja nicht für verkette Listen:

    template<typename T>
    class RefPointer
    {
    public:
        RefPointer(T& x) x_(x) {}
        RefPointer& operator=(const RefPointer& other)
        {
            RefPointer tmp(other);
            (*this).~RefPointer();
            new(this) RefPointer(tmp);  // ok, hier ist ein Pointer beteiligt...
            return *this;
        }
        T& operator*() const { return x_; }
        operator RefPointer<const T>() const
        {
            return RefPointer<const T>(x_);
        }
    private:
        T& x_;
    };
    

    Alles eine Frage der kriminellen Energie, die man aufbringt 🙂 - dass new einen Pointer zurückgibt, kann man so nat. nicht ändern.



  • pumuckl schrieb:

    Hmmm... schrieb:

    Verkettete Listen sind IMHO auch ohne Zeiger möglich.

    Das wird sicher einige hier interessieren, wie du eine Verkettete Liste (am Betsen eine double linked list) in C++ ohne Zeiger implementieren willst. Hast du dazu ein Beispiel oder einen Link auf Lager?

    Ich habe kein Beispiel, aber denkbar wären zwei Ansätze:
    1. Alle Listenelemente befinden sich bereits in einem großen Array, so daß die Links einfach Indezes in dieses Array sind.
    2. Statt Zeigern werden Referenzen verwendet.



  • Hmmm... schrieb:

    Ich habe kein Beispiel, aber denkbar wären zwei Ansätze:
    1. Alle Listenelemente befinden sich bereits in einem großen Array, so daß die Links einfach Indezes in dieses Array sind.
    2. Statt Zeigern werden Referenzen verwendet.

    Dann hast Du jetzt zwei Möglichkeiten:
    1. Glaube uns, dass beide Ansätze in eine Sackgasse führen werden.
    2. Implementiere eine solche Liste und komme selbst an den Punkt wo Du mit Referenzen nicht weiterkommst.

    (Ansatz 1 würde jedenfalls schonmal die Flexibilität einer solchen Liste zerstören, da der Array eine feste Länge haben müsste)



  • CStoll schrieb:

    Hmmm... schrieb:

    CStoll schrieb:

    optionale Werte - du übergibst NULL für "der Wert interessiert mich nicht"

    Man könnte doch eine Referenz auf einen Wert "interessiert mich nicht" übergeben.

    Und wie soll der Wert aussehen? Hinter einer Referenz steht IMMER eine existierende Variable, ein Zeiger kann auf NULL verweisen.

    CStoll schrieb:

    Sondermarkierungen, z.B. für das Ende einer verketteten Liste
    wo wir gerade bei Listen sind: Die Nachfolger-Beziehungen zwischen Elementen können/müssen sich während der Laufzeit auch ändern

    Verkettete Listen sind IMHO auch ohne Zeiger möglich.

    Dann zeig doch mal, wie du DAS anstellen willst.

    ich weiss nicht wie er es anstellen würde aber ich würde es mit einer referenz auf einem dummy wert machen.
    wer sagt das das ende einer liste mit NULL definiert sein muss ?
    aber ich tendiere auch zu deiner art der anwendung.

    ich verwende referenzen eigentlich so:
    alles was pointertype(auch arrays) ist, wird als pointer weitergegeben (da pointer auch NULL sein können)
    alles was am stack liegt(ausnahme primitive datentypen), bzw "garantiert" existiert und nie NULL sein kann, wird als referenz übergeben.



  • Hmmm... schrieb:

    1. Alle Listenelemente befinden sich bereits in einem großen Array, so daß die Links einfach Indezes in dieses Array sind.

    Was meinst du, was der Prozessor aus einem Zeiger macht? Einen Index auf ein sehr großes Array (genannt "Speicher") 😉

    2. Statt Zeigern werden Referenzen verwendet.

    Kannst du machen - aber damit kann die Liste nur sehr eingeschränkt verwendet werden (eine Referenz lässt sich nach ihrer Erzeugung nicht mehr mit regulären Mitteln umbiegen - solche Brachiallösungen, wie sie camper präsentiert hat, sind extrem grenzwertig (wenn nicht sogar undefiniert)).



  • LordJaxom schrieb:

    2. Implementiere eine solche Liste und komme selbst an den Punkt wo Du mit Referenzen nicht weiterkommst.

    Das Problem bei einer Heap-basierten Liste wird sein, daß new und delete mit Zeigern arbeiten. Wenn man aber Funktionen bereitstellt wie etwa:

    ListElement& newListElement()
    {
        return * new ListElement;
    }
    
    void deleteListElement (ListElement &l)
    {
        delete &l;
    }
    

    Dann könnte man bestimmt eine beliebige Listen-Implementation nehmen und sie auf Referenzen umstellen.



  • Dann versuch mal, in dieser Referenz-basierten Listenimplementation Elemente irgendwo in der Mitte einzufügen oder zu entfernen - dazu müsstest du nie Nachfolger/Vorgänger-Verweise umbiegen, was bei Referenzen nicht möglich ist.



  • Zu Campers brutalem Umbiegemanoever hat Herb Sutter auch schon seinen Senf gegeben:
    http://www.gotw.ca/gotw/023.htm



  • Wie wollt ihr auf ein Array zugreifen ohne Zeiger zu verwenden?
    Mit [] geht es auf jeden Fall nicht, da das Zeigerarithmetik ist.


  • Mod

    pumuckl schrieb:

    Zu Campers brutalem Umbiegemanoever hat Herb Sutter auch schon seinen Senf gegeben:
    http://www.gotw.ca/gotw/023.htm

    Streng genommen trifft keiner der Kritikpunkte aus dem Artikel in diesem Falle zu (die Klasse ist nicht zum Ableiten da und Exceptions werden auch nicht geworfen). Den Destruktoraufuruf hätte ich mir auch sparen können - das ist nur Gewohnheit. Egal, der Gedanke war mir gekommen, als ich mich eigentlich schon entschlossen hatte, in diesem Thread nichts zu schreiben...

    Was Pointer gegenüber Referenzen auszeichnet, ist nicht so sehr, dass man sie verändern kann, sondern dass der Verweis (d.h. die Adresse) selbst ein Wert ist. Pointerarithmetik ist mit Referenzen völlig undenkbar, wenn wir der Referenz nicht einen Wert geben, der nicht das referenzierte Objekt selbst ist (es geht nicht so sehr um Arithmetik selbst, sondern um die Möglichkeit einer Operation f, so dass für eine Referenz x f(x) auf ein von x verschiedenes - aber davon abhängiges - Objekt verweist). Und ohne Pointerarithmetik kommt man mit dem Speichermodell von C++ nicht weit.


Anmelden zum Antworten