Pointer vs. Reference



  • Okay, gut, dann habe ich da was falsch verstanden. Aber gut, danke für die Aufklärung.

    Hat man für Referenzen dann spezielle Anwendungen? Bzw. wann weiß ich wann ich eine Referenz verwende und wann einen Pointer?



  • Referenzen werden bevorzugt. Gute Gründe trotzdem einen Pointer zu benutzen:
    - Soll auch 0 sein können
    - Soll auf einen Speicherbereich zeigen (ergo man will ihn inkrementieren)
    - Man will ihm später einen anderen Wert zuweisen können

    Mittelgute Gründe trotzdem einen Pointer zu benutzen:
    - Der -> Operator sieht einfach cooler aus.



  • Wenn ich mir verschiedene Quellcodes von größeren Projekten auf GitHub ansehe, finde ich dort irgendwie mehr Pointer als Referenzen. Kann natürlich subjektiv sein.

    Gibt es einen speziellen Grund warum Referenzen bevorzugt werden? Hat es Speichermanagement-Gründe? Ist es falsch wenn ich sagen würde das man im Allgemeinen Smart-Pointer bevorzugen sollte? Oder werden trotz intelligenter Zeiger immer noch Referenzen bevorzugt?



  • Lokart schrieb:

    Wenn ich mir verschiedene Quellcodes von größeren Projekten auf GitHub ansehe, finde ich dort irgendwie mehr Pointer als Referenzen. Kann natürlich subjektiv sein.

    Die überwiegende Mehrheit des Codes auf der Welt ist halt einfach schlecht, damit muss man sich abfinden.

    Lokart schrieb:

    Gibt es einen speziellen Grund warum Referenzen bevorzugt werden?

    Ja, sie können die oben aufgezählten Dinge nicht und sind daher weniger Fehleranfällig.

    Lokart schrieb:

    Hat es Speichermanagement-Gründe?

    Im Allgemeinen eher nicht.

    Lokart schrieb:

    Ist es falsch wenn ich sagen würde das man im Allgemeinen Smart-Pointer bevorzugen sollte?

    Smart-Pointer und Referenzen sind zwei völlig andere Anwendungsgebiete. Referenzen sind normalerweise nicht besitzend. Eine Referenz da zu benutzen, wo ein Smartpointer hingehört, macht natürlich wenig Sinn.

    Lokart schrieb:

    Oder werden trotz intelligenter Zeiger immer noch Referenzen bevorzugt?

    Siehe oben. 😉



  • Verabschiede Dich am besten einfach von dem Gedanken, dass Referenzen was mit Pointern zu tun haben. Das macht eh nur Ärger und trägt meiner Meinung nach auch nicht gerade zur Steigerung des Verständnisses bei.
    Stelle Dir Referenzen einfach als Alias für ein Objekt vor. Überall da, wo Du ein Alies brauchst, solltest Du dann Referenzen nehmen.
    Wenn Du also ein Objekt namens A hast, und darauf eine Referenz namens B, dann ist B nur ein anderer Name für A. Wenn B ein Pointer wäre, dann kannst Du zwar die Adresse von A darin speichern, aber auch Adressen von anderen Objekten oder einen Nullzeiger. Das ist semantisch also stark unterschiedlich zu Referenzen.



  • @Lokart
    Der überwiegende Grossteil aller Referenzen die ich verwende sind const-ref Parameter.
    Dann kommen Output-Parameter (das selbe ohne const).

    Und alles andere sind dann schon Spezialfälle.



  • Referenz und Pointer sind theoretisch das selbe.

    Verabschiede Dich am besten einfach von dem Gedanken, dass Referenzen was mit Pointern zu tun haben.

    Es wird langsam kompliziert; zwar sind sie theoretisch das Selbe (mit ein paar Ausnahmen), ich sollte aber nicht beachten, dass sie etwas miteinander zu tun haben. Das Pointer-Reference-Paradoxon? 😛

    Okay, ich gehe mal davon aus, dass Referenzen einfach nur Aliases sind. Aber wo brauche ich einen Alias für ein Objekt? Mir würde spontan kein praktisches Beispiel einfallen.

    Und wenn

    Die überwiegende Mehrheit des Codes auf der Welt ist halt einfach schlecht, damit muss man sich abfinden.

    Wenn Referenzen aber weniger fehleranfällig sind als Pointer, warum werden dann bei den Sachen die ich mir angesehen habe eher Pointer als Referenzen benutzt?

    Ich nehme mal ein kleines fiktives Programm als Beispiel: dieses Programm lädt enorm große Datenmengen und speichert ihren Wert in Variablen. Nun gibt es ein paar Funktionen die mit diesen Variablen arbeiten. Es wäre doch sinnlos diesen Funktionen Kopien der Variable zu übergeben, würde doch den Speicher unnötig in die Höhe treiben. Meiner Meinung nach ist es hier dann doch völlig egal, ob ich eine Referenz oder einen Pointer verwende?
    Und was, wenn man weiß das z.B. nach 3 Funktionen die Variablen nicht mehr gebraucht werden? Dann lösche ich den Inhalt an den entsprechenden Adressen doch? Aber wie?



  • Lokart schrieb:

    Es wird langsam kompliziert; zwar sind sie theoretisch das Selbe (mit ein paar Ausnahmen), ich sollte aber nicht beachten, dass sie etwas miteinander zu tun haben. Das Pointer-Reference-Paradoxon? 😛

    Technisch sind sie quasi gleich, semantisch nicht.

    Lokart schrieb:

    Okay, ich gehe mal davon aus, dass Referenzen einfach nur Aliases sind. Aber wo brauche ich einen Alias für ein Objekt? Mir würde spontan kein praktisches Beispiel einfallen.

    Wie wäre es mit: Immer wenn man einen "read only" Parameter übergibt, bei dem nicht kopiert werden soll; oder wenn man einen Parameter aus einer Funktion heraus ändern möchte? Eigentlich müsstest du dir nur die Standardbibliothek angucken, die ist voll von Referenzen.

    Lokart schrieb:

    Und wenn

    Die überwiegende Mehrheit des Codes auf der Welt ist halt einfach schlecht, damit muss man sich abfinden.

    Wenn Referenzen aber weniger fehleranfällig sind als Pointer, warum werden dann bei den Sachen die ich mir angesehen habe eher Pointer als Referenzen benutzt?

    Weil siehe was ich geschrieben habe? 😕

    Lokart schrieb:

    Ich nehme mal ein kleines fiktives Programm als Beispiel: dieses Programm lädt enorm große Datenmengen und speichert ihren Wert in Variablen. Nun gibt es ein paar Funktionen die mit diesen Variablen arbeiten. Es wäre doch sinnlos diesen Funktionen Kopien der Variable zu übergeben, würde doch den Speicher unnötig in die Höhe treiben.

    Wenn die Kopie unnötig ist, dann ist sie unnötig, ja.

    Lokart schrieb:

    Meiner Meinung nach ist es hier dann doch völlig egal, ob ich eine Referenz oder einen Pointer verwende?

    Hier verwendest du sehr wahrscheinlich einen Pointer + Größenangabe (std::size_t), weil:

    cooky451 schrieb:

    - Soll auf einen Speicherbereich zeigen (ergo man will ihn inkrementieren)

    Lokart schrieb:

    Und was, wenn man weiß dass z.B. nach 3 Funktionen die Variablen nicht mehr gebraucht werden? Dann lösche ich den Inhalt an den entsprechenden Adressen doch? Aber wie?

    Hä? Code Beispiel?



  • Lokart schrieb:

    Okay, ich gehe mal davon aus, dass Referenzen einfach nur Aliases sind. Aber wo brauche ich einen Alias für ein Objekt? Mir würde spontan kein praktisches Beispiel einfallen.

    Semantisch ist ein großer Unterschied. Pointer zeigen irgendwo hin. Im Idealfall auf ein Objekt entsprechenden Typs. Ein (int 😉 sollte also auf ein int Zeigen. Ein Nullpointer zeigt nach 0. Bevor Du also mit einem Pointer arbeitest, solltest Du prüfen, ob Du einen Nullpointer erwischt hast. Ein invalider Pointer zeigt irgendwo hin, da kannst Du nix mehr prüfen.

    Eine Referenz muss initialisiert werden, sie darf nicht Null sein. Wenn Du also eine Funktion hast, die eine Referenz erwartet, so musst Du auch ein entsprechendes Objekt angeben. Technisch wird nur der Pointer übergeben, aber auch die Funktion weiß, da sie ja eine Referenz bekommt, dass dieser Pointer gültig sein muss. Du musst also nicht auf Null prüfen, da das Objekt gültig sein muss.

    Das kann man auch aushebeln, es ist also nicht 100%ig sicher, aber dafür muss man schon quasi Gewalt anwenden. Daher rate ich Dir deutlich dazu, Referenzen zu bevorzugen und Pointer nur da einzusetzen, wo "NULL" bzw. "nullptr" ein valides Argument sein sollen.

    Lokart schrieb:

    Wenn Referenzen aber weniger fehleranfällig sind als Pointer, warum werden dann bei den Sachen die ich mir angesehen habe eher Pointer als Referenzen benutzt?

    Weil die viele Entwickler, die C++ programmieren, kein C++ programmieren können.

    Lokart schrieb:

    Meiner Meinung nach ist es hier dann doch völlig egal, ob ich eine Referenz oder einen Pointer verwende?

    Richtig.
    Hier solltest Du Dich entscheiden, was Du mitteilen möchtest. Soll das ein Zeiger auf ein oder viele Objekte sein (PixelColor 😉 oder ein Array (PixelColor []) oder ist das Objekt, dass halt sehr groß ist, aber existieren auch muss (BitMap640x320 &).

    Hier würde ich eher eine (Bitmap &) nehmen, die den Zeiger auf die vielen Farbinformationen managt, dieses Objekt wäre dann wieder deutlich kleiner und problemlos als Referenz zu übergeben, wenn Du z.B. in die Bitmap reinzeichnen möchtest. Referenz deswegen, weil Du ja nicht auf einen NULL- oder invaliden Pointer zeichnen willst, sondern definitiv auf eine existierende Bitmap.

    Lokart schrieb:

    Und was, wenn man weiß das z.B. nach 3 Funktionen die Variablen nicht mehr gebraucht werden? Dann lösche ich den Inhalt an den entsprechenden Adressen doch? Aber wie?

    delete?

    Ich glaube, ich verstehe die Frage nicht...
    Wenn Du Speicher alloziierst und den Block als Pointer an Methoden übergibst, wäre es ratsam, wenn derjenige, der den Speicher alloziiert hat, diesen auch wieder freigibt.

    Dein fiktives Programm müsste genauer spezifiziert sein, um konkrete Lösungen zu beschreiben. ^^



  • #include <iostream>
    
    int f1() {
    	/* unmengen an quellcode, zig milliarden zeilen, unmengen an speicherverbrauch */
    	return 1;
    }
    
    int f2(int &a) {
    	return a * 2;
    }
    
    int f3(int &a) {
    	return a * 3;
    }
    
    int f4() {
    	return 1024;
    }
    
    int main() {
    	// lade die unmengen an daten
    	int a = f1();
    
    	// die erste funktion die a haben will:
    	std::cout << f2(a) << std::endl;
    
    	// die zweite funktion die a haben will
    	std::cout << f3(a) << std::endl;
    
    	// eine vierte funktion, die nicht mit a arbeitet, folglich könnte ich den speicher
    	// der im moment noch von a belegt wird, doch freigeben?
    	std::cout << f4() << std::endl;
    
    	return 0;
    }
    

    Vor Aufruf von f4() weiß ich, dass ich a nicht mehr brauche. Wie gebe ich den Speicher nun frei?



  • Lokart schrieb:

    Vor Aufruf von f4() weiß ich, dass ich a nicht mehr brauche. Wie gebe ich den Speicher nun frei?

    Etwa so?

    #include <iostream>
    
    typedef int UnmengeAnDatan;
    
    UnmengeAnDaten * f1() {
    	/* unmengen an quellcode, zig milliarden zeilen, unmengen an speicherverbrauch */
    	return new UnmengeAnDaten(1);
    }
    
    UnmengeAnDaten f2(UnmengeAnDaten const &a) {
    	return a * 2;
    }
    
    UnmengeAnDaten f3(UnmengeAnDaten const &a) {
    	return a * 3;
    }
    
    int f4() {
    	return 1024;
    }
    
    int main() {
    	// lade die unmengen an daten
    	UnmengeAnDatan * a = f1();  // Pointer
    
    	if( a )
    	{
    	  UnmengeAnDaten const & alias = *a;
    
    	  // die erste funktion die a haben will:
    	  std::cout << f2( alias ) << std::endl;
    
    	  // die zweite funktion die a haben will
    	  std::cout << f3( alias ) << std::endl;
    
    	  delete a;  // bei Arrays delete [] a, vielleicht eine f1_free( a )-Funktion
    	             // die das sicher weiß?
    	}
    
    	// eine vierte funktion, die nicht mit a arbeitet, folglich könnte ich den speicher
    	// der im moment noch von a belegt wird, doch freigeben?
    	std::cout << f4() << std::endl;
    
    	return 0;
    }
    

    Das Alias brauchst Du nicht, Da Du mit if(a) sicherstellst, dass a existiert. Du kannst also auch f2 und f3 mit (*a) füttern.

    const (siehe f2, f3) solltest Du immer dann verwenden, wenn Du die Daten, die referenziert werden nicht verändern möchtest.

    PS: bei f1 bekommst Du ggfs. eine Exception um die Ohren geschmissen... aber das ist ein anderes Thema. if( a ) aus Prinzip, wer weiß, was Du von f1 geliefert bekommst, vielleicht fängt f1 die Exception und liefert NULL?
    Ansonsten mag ich auch new( std::nothrow ), wenn ich auf die Exception gut verzichten kann...



  • @Lokart: Ich glaube, wir reden hier aneinander vorbei. Wenn du zig Milliarden Daten zu verwalten hast, dann stellt sich erst einmal die Frage, was das für Daten sind. Als nächstes stellt sich die Frage, von wem und wie sie zu verwalten sind. Werden diese Fragen richtig beantwortet, brauchst du dir keine Sorgen mehr um deinen Speicherplatz machen.

    An dieser Stelle sollte man auch mal klar stellen, für welchen Zweck new gedacht ist. new benutzt du, wenn du das Objekt über den Scope hinaus am Leben erhalten musst (siehe Xins Beispiel).



  • Okay, langsam leuchtet es mir ein. Erstmal Danke an Alle für die ausführliche Erklärung.

    Da ich gerade bisschen am Programmieren bin noch etwas über Vektoren, die mit dem Thema zwar nichts zu tun hat, aber wenn der Thread schon steht:

    Kann es sein, dass die folgende Art Elemente in einen Vektor einzutragen ein C++11 Feature ist?

    std::vector< int > b{ 1, 2, 3 ,4 };
    

    Irgendwie findet mein MSVC 2010 das nicht so knorke, obwohl die Initialisierung auf diese Art ja eigentlich machbar sein müsste?

    Und:
    Die Handhabung von mehrdimensionalen Vektoren (bzw. Vektoren von Vektoren) ist mir noch nicht so klar.

    std::vector< std::vector< int > > b;
    

    Bedeutet das b ein Vektor von Vektoren mit dem Typ int ist - aber wie kriege ich da jetzt Elemente rein?
    Ich will nämlich einige Dinge für mein aktuelles Teil in einem Vektor speichern - bestehend aus einem Integer und "einem dazugehörigen Integer" (gibts wohl in PHP Arrays mit Keys => Values). Bestenfalls sogar noch unterteilt in Kategorien, womit ich eigentlich bei "einem Vektor von Vektoren von Vektoren" wäre, aber ich scheitere ja schon an der zweiten Dimension.
    Damit man sich das besser vorstellen kann hier eine kleine "Verdeutlichung":

    Person_1 =>
    	Autos =>
    		bmw
    		audi
    	Frauen =>
    		hannah
    		silke
    		christina
    	[...]
    		[...]
    

    Sprich Hauptelement ist "Person_1", zu Person_1 gehört "Autos" und "Frauen". Die Werte von "Autos" und "Frauen" sind eben die oben stehenden Sachen.



  • Lokart schrieb:

    Kann es sein, dass die folgende Art Elemente in einen Vektor einzutragen ein C++11 Feature ist?

    std::vector< int > b{ 1, 2, 3 ,4 };
    

    Irgendwie findet mein MSVC 2010 das nicht so knorke, obwohl die Initialisierung auf diese Art ja eigentlich machbar sein müsste?

    Ja das ist ein C++11 Feature. Selbst in MSVS 2012 haut das noch nicht hin.

    Lokart schrieb:

    Die Handhabung von mehrdimensionalen Vektoren (bzw. Vektoren von Vektoren) ist mir noch nicht so klar.

    std::vector< std::vector< int > > b;
    

    Erstmal: Da du ja offensichtlich schon C++11 nutzt, ist so ein Konstrukt nicht mehr so oft nötig. std::vector<std::vector> bedeutet nämlich, dass du eine Liste von Listen hast. Das ist nicht nötig, da die innere Dimension meist eine bekannte feste Größe hat und demnach nicht dynamisch sein muss. Ergo nicht std::vector<std::vector> sondern std::vector<std::array>

    Lokart schrieb:

    Bedeutet das b ein Vektor von Vektoren mit dem Typ int ist - aber wie kriege ich da jetzt Elemente rein?

    Na, wenn der Container einen Container will, dann musst du ihm einen geben:

    vecor< vector<int> > aussen;
    vector<int> innen = { 1, 2, 3, 4, 5 };
    aussen.push_back( innen );
    cout << endl << aussen[0][0];
    

    Lokart schrieb:

    bestehend aus einem Integer und "einem dazugehörigen Integer" (gibts wohl in PHP Arrays mit Keys => Values). Bestenfalls sogar noch unterteilt in Kategorien, womit ich eigentlich bei "einem Vektor von Vektoren von Vektoren" wäre, aber ich scheitere ja schon an der zweiten Dimension.
    Damit man sich das besser vorstellen kann hier eine kleine "Verdeutlichung":

    Person_1 =>
    	Autos =>
    		bmw
    		audi
    	Frauen =>
    		hannah
    		silke
    		christina
    	[...]
    		[...]
    

    Sprich Hauptelement ist "Person_1", zu Person_1 gehört "Autos" und "Frauen". Die Werte von "Autos" und "Frauen" sind eben die oben stehenden Sachen.

    Aso, das willst du also. Ganz schön viele Frauen hat so eine Person :D. Ich hab da mal ein Versuch gemacht. Herausgekommen ist das:

    #include <iostream>
    #include <map>
    #include <string>
    #include <vector>
    using namespace std;
    
    enum Werte { Autos, Frauen };
    
    int main()
    {
    	map< string, map<Werte,vector<string>> > Personen;
    
    	// Zu Person_1
    	{
    		map<Werte,vector<string>> zu_person_1;
    
    		vector<string> autos;
    		autos.push_back("bmw");
    		autos.push_back("audi");
    		zu_person_1[Autos] = autos;
    
    		vector<string> frauen;
    		frauen.push_back("hannah");
    		frauen.push_back("silke");
    		frauen.push_back("christina");
    		zu_person_1[Frauen] = frauen;
    
    		Personen["Person_1"] = zu_person_1;
    	}
    
    	// Testausgaben
    	{
    		cout << endl << "Autos: ";
    		for(auto& a : Personen["Person_1"][Autos])
    			cout << a << ' ';
    
    		cout << endl << "Frauen: ";
    		for(auto& f : Personen["Person_1"][Frauen])
    			cout << f << ' ';
    	}
    }
    


  • Vielen Dank! 🙂



  • cooky451 schrieb:

    Lokart schrieb:

    Es wird langsam kompliziert; zwar sind sie theoretisch das Selbe (mit ein paar Ausnahmen), ich sollte aber nicht beachten, dass sie etwas miteinander zu tun haben. Das Pointer-Reference-Paradoxon? 😛

    Technisch sind sie quasi gleich, semantisch nicht.

    Technisch können sie gleich sein. Sind sie aber nicht in jedem Fall, und müssen sie auch nicht. Ich würde mich davon verabschieden, dass Refernzen was mit Pointern zu tun haben.

    [quote:55ebf8ce7b="ISO/IEC
    14882/2011 8.3.2§4"]It is unspecified whether or not a reference requires storage
    Das sagt eigentlich deutlich, dass bei Referenzen technisch nicht zwangsläufig mit Zeigern realisiert werden müssen...

    PS: Achso, semantisch ist natürlich der folgende Absatz viel interessanter:
    [quote:55ebf8ce7b="ISO/IEC
    14882/2011 8.3.2§5"]There shall be no references to references, no arrays of references, and no pointers to references. The
    declaration of a reference shall contain an initializer [...] A reference shall be initialized to refer to a valid object
    or function. [ Note: in particular, a null reference cannot exist in a well-defined program, because the only
    way to create such a reference would be to bind it to the “object” obtained by dereferencing a null pointer,
    which causes undefined behavior.[...]
    Das zeigt schon sehr deutlich die Unterschiede auf.



  • Tachyon schrieb:

    Das sagt eigentlich deutlich, dass bei Referenzen technisch nicht zwangsläufig mit Zeigern realisiert werden müssen...

    Ja, das ist wie mit OOP, wo Nachrichten ausgetauscht werden, statt Funktionen zu rufen. Man könnte statt die Funktion zu rufen, auch eine Nachricht per Messagebox ausgeben und den Benutzer bitten, die Nachricht an ein anderes Objekt weiter zu leiten. Sowas ist grundsätzlich nicht von der OOP-Idee ausgeschlossen. In der Praxis haben sich Funktionspointer bewährt.

    Ähnlich ist das hier. Natürlich muss man Referenzen nicht mit Zeigern implementieren. Man könnte zum Beispiel das Objekt kopieren, bearbeiten lassen und bei Rückkehr der Funktion auf das Originalobjekt zurückkopieren. Semantisch wäre das eine dem Standard entsprechende Vorgehensweise, die selbstverständlich auch zum gleichen Ergebnis führt. Es wird lediglich etwas kompliziert, wenn man eine Referenz als Teil eines anderen Objektes hat, aber da lässt sich bestimmt auch was über die MMU tricksen.

    Finde ich gut, dass Du drauf hingewiesen hast. 👍
    Aus irgendeinem Grund sind sich die Compilerentwickler aber meines Wissens relativ einig gewesen, Referenzen mit Pointern zu realisieren.



  • Xin schrieb:

    [...]

    Du hast die Message nicht verstanden. Die Message war nicht: Es wird nicht mit Zeigern relisiert, sondern irgendwie magisch hingefrickelt.

    Die Message war: Es darf einen nicht intressieren wie es realisiert wird, weil Annahmen darüber gefährlich sein können und auch sind. Und ultimativ auch: Es braucht einen nicht zu interessieren.

    Xin schrieb:

    Aus irgendeinem Grund sind sich die Compilerentwickler aber meines Wissens relativ einig gewesen, Referenzen mit Pointern zu realisieren.

    Meines Wissens machen die Compilerentwickler es so, wie es kontextabhängig am meisten Sinn hat.



  • Tachyon schrieb:

    Xin schrieb:

    [...]

    Du hast die Message nicht verstanden. Die Message war nicht: Es wird nicht mit Zeigern relisiert, sondern irgendwie magisch hingefrickelt.

    Du hast meine Message nicht verstanden.

    Wir arbeiten mit Computern. Es gibt Best-Practices. Manchmal nennt man sie auch Hochsprachen, Design-Pattern oder Standards. Computer haben eine Funktionsweise und Pointer sind dabei nicht etwas magisch hingefrickeltes, sondern eine grundlegende Lösung ohne Alternative. Nicht nur eine Best-Practice, sondern eine Grundlage der Funktion.

    Der Standard schreibt nicht vor Pointer zu verwenden. Wir können hier gerne einen Einsteiger mit einer Philosophie über den C++-Standard beglücken, aber es wird ihm wesentlich mehr nutzen, wenn er weiß, dass Referenzen technisch über Pointer realisiert werden. Das erklärt ihm vergleichsweise einfach Referenzen, wie sich Referenzen verhalten und warum bei sizeof( int & ) ein bestimmtes Ergebnis zu erwarten ist.

    Wenn also jeder hammerkompatible Nägel herstellt, Hämmer dafür bekannt sind, um Nägel in die Wand zu referenzieren (<-man beachte das Wort), er die Funktionsweise eines Hammers begreifen kann, damit auch den Nagel in die Wand bekommt, dann ist der Thread für ein praktisches Problem erledigt.

    Auch wenn das Gesetz sagt, dass Du zum Nägelklopfen auch andere Werkzeuge verwenden darfst, dann kannst das mit einem Theoretiker gerne ausdiskutieren. Ich bin diesbezüglich so einer, denn ich entwickle einen Compiler. Und auch ich will darüber nicht philosophieren, da wir nunmal Computer verwenden, die Zeiger benötigen.

    Um meine Message etwas deutlicher auszudrücken: Gibt es irgendjemanden, den es interessiert, dass der Standard Zeiger nicht explizit vorschreibt?



  • [quote="Xin"]

    Tachyon schrieb:

    Xin schrieb:

    [...]

    D
    Der Standard schreibt nicht vor Pointer zu verwenden. Wir können hier gerne einen Einsteiger mit einer Philosophie über den C++-Standard beglücken, aber es wird ihm wesentlich mehr nutzen, wenn er weiß, dass Referenzen technisch über Pointer realisiert werden. Das erklärt ihm vergleichsweise einfach Referenzen, wie sich Referenzen verhalten und warum bei sizeof( int & ) ein bestimmtes Ergebnis zu erwarten ist.

    Genau, Wie sehr es dem Einsteiger nutzt, sieht man ja an der Frage des TOs (die Frage kommt hier regelmäßig): "Soll ich Pointer oder Referenzen benutzen? Ist ja technisch das Gleiche."
    sizeof(T &) verhält sich übrigens genau so, wie man es bei einem Alias von T erwarten würde und völlig anders als bei einem Pointer.


Anmelden zum Antworten