Pointer vs. Reference



  • Swordfish schrieb:

    Vielleicht steh ich grad sowas von auf der Leitung... Kann mir bitte jemand eine Konstellation zeigen in der das referenzierte Objekt vor der Referenz aus dem Scope geht und die Referenz weiterlebt!? 😮

    Evtl. könnte man da etwas mit Threads konstruieren...



  • Ich grabe den Thread einfach nochmal aus, weil mir etwas nicht so ganz klar ist:

    Folgender Quellcode:

    #include <iostream>
    
    class T {
    public:
    	T(const int a) {
    		m_A = a;
    	}
    
    	int _(int *a) {
    		return *a + m_A;
    	}
    private:
    	int m_A;
    };
    
    int main() {
    	T* test = new T(42);
    
    	int a = 100;
    
    	std::cout << test->_(&a) << std::endl;
    
    	delete test;
    
    	std::cout << test->_(&a) << std::endl;
    
    	return 0;
    }
    

    Ein Pointer zur Klasse T namens Test. Ausgabe:

    142
    -17891502
    

    Mir ist schonmal nicht ganz so klar, warum ich nach dem delete noch mit der Klasse arbeiten kann? Verstehe ich delete hier falsch?

    Aber was ganz merkwürdig ist:
    Ändere ich die Funktion _ wie folgt ab:

    int _(int *a) {
    		return *a + 100;
    	}
    

    Ist das Ergebnis:

    200
    200
    

    Huh? Warum? Das erste Ergebnis ist mir klar, das zweite aber weniger (in Anbetracht der oberen Ausgabe).



  • Undefiniertes Verhalten.



  • Lokart schrieb:

    Mir ist schonmal nicht ganz so klar, warum ich nach dem delete noch mit der Klasse arbeiten kann? Verstehe ich delete hier falsch?

    Oh, ein Outing als digitaler Nekrophiler...

    Die Klasse wird ausgelöscht, aber deswegen löst sie sich ja nicht gleich in Luft auf. Klar, liegen die Daten verbuddelt in der Erde, aber solange keine neuen Daten auf den Friedhof leben, bleibt die Datenleiche nunmal der Hauptbewohner dieser Speicherstelle.

    Du buddelst die Sachen jetzt wieder aus und da sich in der Zwischenzeit auf dem Speicherbereich auf den test zeigt, nichts Neues angesiedelt hat, poppst Du die Überreste lockerflockig durch die Methode _.

    Niemand hat ein Problem damit, wenn Du Existenzen zerstörst, aber Deine Methoden, sie nach ihrem Tod auch noch in Parameter zu pushen und poppen, sind unschön und wird von den gesellschaftlichen Normen nicht getragen.

    Du könntest Dein Opfer auch auslöschen, indem Du temp mit NULL reinitialisierst, damit Du jedesmal, wenn Du, wenn Dich mal wieder das Verlangen überkommt, den Hinweis 'Anwendung reagiert nicht mehr'. erhältst. :->



  • Klassen funktionieren anders als du denkst.

    Zu allererst muss klar werden, was passiert, wenn man eine Klasse, die im Freispeicher allokiert wurde, wieder freigibt.

    Das einzige, was allokiert wird, sind die Member-variablen/konstanten.
    Also praktisch in deinem Beispiel m_A .
    Diese liegen jetzt hintereinander im Freispeicher;
    wenn du nun die Instanz wieder zerstörst und den Speicher freigibst, dann wird der Destruktor für die Instanz und alle Member aufgerufen. Und der Speicher freigegeben.

    Die Funktionen sind dabei völlig unabhängig von der Instanz. Man kann sie sogar ohne Instanz aufrufen.
    Dabei wird lediglich der this -Parameter 0 sein. Und this zeigt einfach auf diese Membervariablen im Freispeicher.

    Wenn du jetzt die Funktion _ aufrufst, kannst du dir das so vorstellen:

    std::cout << _(&test, &a) << std::endl;///Sieht nachher definitiv *nicht* so aus!
    

    Da du in deiner zweiten Version nicht auf die Membervariablen zugreifst, wird er this-Zeiger ignoriert,
    und du kannst selbst mit einem Zeiger auf wilden Murks die Memberfunktion sauber und definiert aufrufen.

    Das einzige, was bei der ersten Funktion undefiniert ist, ist der Zugriff auf Membervariablen eines ungültigen Objekts - also eines, dass nicht erstellt wurde oder schon wieder zerstört wurde.

    P.S.:

    Wenn du in einer Memberfunktion eine Membervariable nutzt, wird davor vom Compiler (kann aber auch manuell gemacht werden, macht manchmal Sinn) ein this-> gestellt.



  • Sone schrieb:

    Wenn du jetzt die Funktion _ aufrufst, kannst du dir das so vorstellen:

    std::cout << _(&test, &a) << std::endl;///Sieht nachher definitiv *nicht* so aus!
    

    Es sieht so gar definitiv so aus. (auf die hier zwangsläufig folgende Diskussion, dass der Standard das so nicht vorgibt, werde ich nicht eingehen...)

    Schöne Erklärung, leider so wenig makaber, wo es sich doch derart aufdrängt ;-). 👍



  • Xin schrieb:

    Sone schrieb:

    Wenn du jetzt die Funktion _ aufrufst, kannst du dir das so vorstellen:

    std::cout << _(&test, &a) << std::endl;///Sieht nachher definitiv *nicht* so aus!
    

    Es sieht so gar definitiv so aus. (auf die hier zwangsläufig folgende Diskussion, dass der Standard das so nicht vorgibt, werde ich nicht eingehen...)

    Nein, ich meinte, von den Bezeichnern her sieht es nicht so aus 😃
    Die sind dann doch irgendwelche Buchstaben mit Nummern (ich dachte immer, Hashes)?

    Das der this-Parameter der erste ist, ist implementations-spezifisch, AFAIR.



  • Xin schrieb:

    Lokart schrieb:

    Mir ist schonmal nicht ganz so klar, warum ich nach dem delete noch mit der Klasse arbeiten kann? Verstehe ich delete hier falsch?

    Oh, ein Outing als digitaler Nekrophiler...

    Die Klasse wird ausgelöscht, aber deswegen löst sie sich ja nicht gleich in Luft auf. Klar, liegen die Daten verbuddelt in der Erde, aber solange keine neuen Daten auf den Friedhof leben, bleibt die Datenleiche nunmal der Hauptbewohner dieser Speicherstelle.

    Du buddelst die Sachen jetzt wieder aus und da sich in der Zwischenzeit auf dem Speicherbereich auf den test zeigt, nichts Neues angesiedelt hat, poppst Du die Überreste lockerflockig durch die Methode _.

    Niemand hat ein Problem damit, wenn Du Existenzen zerstörst, aber Deine Methoden, sie nach ihrem Tod auch noch in Parameter zu pushen und poppen, sind unschön und wird von den gesellschaftlichen Normen nicht getragen.

    Du könntest Dein Opfer auch auslöschen, indem Du temp mit NULL reinitialisierst, damit Du jedesmal, wenn Du, wenn Dich mal wieder das Verlangen überkommt, den Hinweis 'Anwendung reagiert nicht mehr'. erhältst. :->

    Danke, nicht nur für die Erklärung - ich musste lachen ;> Vor allem "Digitaler Nekrophiler" gibt mir grad alles. Ich suche schon längere Zeit n guten Blognamen; ich glaube das kam gerade in die Favoriten 😃

    Und danke für die restlichen Erklärungen. So ergibt das natürlich Sinn. Ich werde zukünftig darauf acht geben nicht mit Leichen zu arbeiten 🙂



  • Begraben darfst Du sie ja. Nicht, dass hier Totengräber in Verruf geraten.



  • Wir hatten diese Frage schon soo oft in der gleichen Form. Warum ist sie immer noch nicht bei den FAQs?

    An den Threadersteller:
    http://www.parashift.com/c++-faq/references.html
    www.google.de Baaam!



  • [Rewind] schrieb:

    www.google.de Baaam!

    Oida!


Anmelden zum Antworten