Zeiger oder Referenz
-
Konrad Rudolph schrieb:
Nun, es ging hier doch nur um Parameterübergabe per Zeiger/Referenz und hier entsteht wohl kaum ein Programmieroverhead durch Zeigerverwendung (zumindest, wenn man sich um Nullwerte keine Sorgen macht).
Ja, das stimmt.
Ich mein ja nur. Wenn wir's schon von Referenzen vs. Zeiger haben.

-
Power Off schrieb:
Einziges gutes Argument fuer Zeiger, das mir grade einfaellt, ist, dass die Anzahl von Konstruktoraufrufen durch die Verwendung von Zeigern reduziert werden kann. Dies hat einen definitiven Performance-Impact.
versteh ich nich
im zusammenhang mit referenzen die als argument einer funktion übergeben werden?
wo finden da konstruktorenaufrufe statt?
-
Sovok schrieb:
Power Off schrieb:
Einziges gutes Argument fuer Zeiger, das mir grade einfaellt, ist, dass die Anzahl von Konstruktoraufrufen durch die Verwendung von Zeigern reduziert werden kann. Dies hat einen definitiven Performance-Impact.
versteh ich nich
im zusammenhang mit referenzen die als argument einer funktion übergeben werden?
wo finden da konstruktorenaufrufe statt?Z.B. bei dieser Sequenz:
#include <string> using std::string; void func( const string& str ) { // ... } void func2( void ) { func( "alpha" ); // versteckter Konstruktor-Aufruf: es wird ein temporaeres string-Objekt angelegt // und danach wieder vernichtet. string c = "alpha" + string("beta"); // 2 Konstruktor-Aufrufe, 1 Destruktor-Aufruf, // 1 operator+() Aufruf }
-
Power Off schrieb:
string c = "alpha" + string("beta"); // 3 Konstruktor-Aufrufe, 2 Destruktor-Aufrufe, // 1 operator+() Aufruf }ich zähle aber nur 2 ctor-aufrufe, 1 dtor-aufruf und 1 op+()-aufruf.
/** * @brief Concatenate C string and string. * @param lhs First string. * @param rhs Last string. * @return New string with value of @a lhs followed by @a rhs. */ template<typename _CharT, typename _Traits, typename _Alloc> basic_string<_CharT,_Traits,_Alloc> operator+(const _CharT* __lhs, const basic_string<_CharT,_Traits,_Alloc>& __rhs);
-
volkard schrieb:
ich zähle aber nur 2 ctor-aufrufe, 1 dtor-aufruf und 1 op+()-aufruf.
Stimmt, hast recht. Werd's gleich korrigieren!

-
vorteil von zeigern?
void func( const string* str ) { // ... } void func2( void ) { func( &string ( "alpha" ) ); //wohl eher string c = string ( "alpha" ) + string("beta"); //weil "alpha" sonst nur n zeiger is zu dem du addierst //beim zweiten kann ich den vorteil von zeigern auch nich nachvollziehn //geht schliesslich garned mit zeigern }[/quote]
-
Gast4 schrieb:
volkard hat sowieso Unrecht.
Falsch geraten, Volkard hat immer Recht (naja, fast). Er wird schliesslich nicht umsonst "The Godfather" genannt.

Trotzdem hab ich seine Ansichten bzgl. Referenzen vs. Zeiger in diesem Punkt nie nachvollziehen können. Mir ist es ehrlich gesagt zu unintuitiv, anhand semantischer Feinheiten zu erlesen, was ein Programm macht. Mir ist zB vollkommen egal, ob da
add_something(foo)oder
add_something(&foo)steht. Das einzige was mich interessiert, ist, dass something zu foo addiert wird.
-
Mein Senf muss auch noch dazu.
Ich mache es oft so, dass ich durch die Wahl anzeige was in der Methode passiert.
Nimmt die Methode einen Pointer, dann kann man sich sicher sein, dass die Methode dem Paramerter verändert.
Nimmt die Methode eine (const) Referenz, dann ist man sich sicher, dass die Methode den Parameter nicht verändern kann.Wenn ich programmiere, dann weiß ich ja was die Methoden die ich aufrufe machen.
Wenn ich mir später meinen Code wieder durchsehe und Methodenaufrufe mit '&' sehe, dann weiß ich sofort.. oha.. der will einen Pointer -- gut da passen wir mal auf.
-
Also ich kann volkards Meinung in dem Punkt jetzt auch nicht ganz nachvollziehen. Vielleicht ist das aber auch Teil einer Studie und er will nur schauen wieviele Leute in den nächsten Wochen einfach seine Meinung weiterplappern. Vielleicht kommt er aber auch nachher mit dem Bombenargument und begründet seine Meinung zu Pointern.
Ob die Funktion etwas mit dem übergebenen Objekt macht erkenne ich daran ob die übergebene Referenz const ist oder nicht und Pointer benutze ich nur wenn es mit Referenzen nicht geht bzw. umständlicher wäre. Pointer auf 0 prüfen macht meiner Meinung nach nur dann Sinn wenn das Objekt auch 0 sein kann, also zusätzlich zur Zeigerfunktion einen Status darstellt (diverse Libs machen da regen Gebrauch von).
-
(naja, fast)
genau das meinte ich

-
hehejo schrieb:
Nimmt die Methode einen Pointer, dann kann man sich sicher sein, dass die Methode dem Paramerter verändert.
Nimmt die Methode eine (const) Referenz, dann ist man sich sicher, dass die Methode den Parameter nicht verändern kann.Warum macht man das nicht gleich nur mit Referenzen?
void func( const alpha& a ); // a kann nicht geaendert werden void func( alpha& a ); // a kann geaendert werden
-
Sovok schrieb:
string c = string ( "alpha" ) + string("beta"); //weil "alpha" sonst nur n zeiger is zu dem du addierstDas macht nix, weil es einen operator+( const char*, const string& ) gibt, den Volkard ja aufgelistet hat.
Also ist:string c = "alpha" + string("beta");equivalent zu:
string c( operator+( "alpha", string( "beta" ) ) );
-
Sovok schrieb:
//wohl eher string c = string ( "alpha" ) + string("beta"); //weil "alpha" sonst nur n zeiger is zu dem du addierst }Nein, siehe Volkards letzten Kommentar und seinen Auszug aus den Standard-Headerdateien.
-
groovemaster schrieb:
Trotzdem hab ich seine Ansichten bzgl. Referenzen vs. Zeiger in diesem Punkt nie nachvollziehen können. Mir ist es ehrlich gesagt zu unintuitiv, anhand semantischer Feinheiten zu erlesen, was ein Programm macht. Mir ist zB vollkommen egal, ob da
add_something(foo)oder
add_something(&foo)steht. Das einzige was mich interessiert, ist, dass something zu foo addiert wird.
sematische feinheiten? jup, die würden mich ankotzen. ich will klaren uen einfachen code.
deswegen will ich keine semantischen feinheiten ausdeuteln müssen, sondern *sofort* sehen, was los ist. insbesondere will ich *nicht* überlegen müssen, was die funktion denn bewerkstelligt. ich kann nicht immer aus dem namen genau folgern, was die funktion macht. vor allem, wenn fremde leute die funktionsnamen erfunden haben.
und das geht so:do_something(foo);//call by value, foo belib unverändertoder
do_something(&foo);//foo wird verändert, weil zeigerund sonst nix.
also beim lesen sehe ich immer ganz genau, ob ich das foo nur zeige oder ob ich's zum verändern hergebe. ach, ist das eine freude, wenn man mal ein kaputtes foo hat, und sich überlegen muß, welche funktiopn foo kaputtet hat. kann ja nur eine mit &foo ewesen sein.
außerdem bin ich auch beim programmieren ein wenig feige. sollte das nicht jeder sein? wenn ich meinen funktionen immer nur foo zu fresen gebe, hab ich echt ein besseres gefühl. die paar mal, wo es dann doch &foo sein muß, mach ich das halt, aber immer bewußt. und da weiß ich, daß keiner an meinen daten rumkritzelt, ohne daß ich das bewußt zugelassen habe.
der stil ist also sowas wie const, nur eben als forderung von der callerseite her und nicht als versprechen von der calleeseite her und ergänzt die strenge typprüfung von c++ dahingehend, daß man schon wieder einen haufen aus-versehen-fehler zu compilerfehlern gemacht hat.
-
Referenzen sind, grob gesagt, die Zeiger fuer Leute die Zeiger nicht raffen...
Man beschneidet seine Programme durch konsequente Nutzung von Referenzen selbst.
Wie prueft man denn die Gueltigkeit einer Referenz? Bei Zeigern geht das ganz einfach. Bei Referenzen ist dies unmoeglich. Zeiger koennen euren Programmen bei geschickter Nutzung zu brutaler Geschwindigkeit verhelfen. Klar, fuer operatoren-ueberladung, catchen, copy c'tor & co. sind Referenzen noetig.
Ich nutze Referenzen quasi nie ausser bei letzterem.
Aber ausserdem gibt es keine Referenz-Arithmetik...
Zeiger
-
Walli schrieb:
Ob die Funktion etwas mit dem übergebenen Objekt macht erkenne ich daran ob die übergebene Referenz const ist oder nicht
das ist aber nur die eine richtung. die funktion verspricht dir, daß da nix geändert wird. bei nur fehlerfreien funktionen, die du benutzt, mag das ok sein. wenn ich schreibe
foo(v);dann brauche ich nicht nachzuschauen, ob foo das v verändert oder nicht. ok, namen wie foo verwenet man nicht. ich brauche aber auch nicht anhand des namens zu überlegen, und das klappt eh nicht immer.
f.add(v);soll jetzt v zu f addiert werden oder f zu v? uneindeutige namen wir's immer geben. übrigens wird hier v genommen und zu f addiert, was ja klar ist, weil v nicht verändert wird.
-
volkard schrieb:
do_something(foo);//call by value, foo belib unverändert do_something(&foo);//foo wird verändert, weil zeigerEs ist genau umgekehrt:
void do_something( const string& foo ); // Call-By-Reference Parameter ("foo" ist eine Referenz) void do_something( string* foo ); // Call-By-Value Parameter ("foo" ist ein Pointer und damit ein Value!)also nochmal:
do_something(foo); // call by reference do_something(&foo); // call by (address) value
-
volkard schrieb:
ok, namen wie foo verwenet man nicht. ich brauche aber auch nicht anhand des namens zu überlegen
Genau dafür sind Namen aber da. Und ich finde, man sollte sich seine Englischkenntnisse durchaus zunutze machen, um Informationen aus dem Code zu ziehen oder welche hineinzustecken.
Dann sind folgende Fälle auch vollkommen klar definiert:
object.add(another_object); // 'another_object' wird zu 'object' hinzugefügt object.add_to(another_object); // 'object' wird zu 'another_object' hinzugefügtAndere Sprachen verfügen nicht wie C++ um eine syntaktische Kennzeichnung von Zeigern und unterstützen ausschließlich Übergaben per Wert, wobei aber durch Verwendung von Referenzobjekten die Übergabewerte trotzdem in den meisten Fällen modifiziert werden können, ohne dass dies für den Aufrufer offensichtlich ist.
Keine dieser Sprachen hat (bei korrekter Benutzung) irgendwelche Probleme mit dieser Tatsache. Wieso also sollte es in C++ Probleme damit geben?
-
+Zeiger! -Referenzen... schrieb:
Referenzen sind, grob gesagt, die Zeiger fuer Leute die Zeiger nicht raffen...
und die mehrheit der leute, die machen, was die mehrheit macht, ohne zu wissen, warum. und früher die leute, die voller spaß experimentell alles mal zu refs machen, um halt das neue zu machen.
Man beschneidet seine Programme durch konsequente Nutzung von Referenzen selbst.
stimmt.
Wie prueft man denn die Gueltigkeit einer Referenz? Bei Zeigern geht das ganz einfach. Bei Referenzen ist dies unmoeglich.
braucht man nicht.
will man ne funktion machen, die wahlweise ein objekt zurückgibt oder einen fehler meldet, kanns per exception gemacht werden. wenns ein schlimmer fehler ist. will man einfach noch dazu sagen können, daß man nix gefunden hat, nimmt man halt zeiger. beim zurückgeben alles klar.
beim übergeben? weiß nicht. muß wohl den raytracer von gestern nochmal lesen. da war viel mit 0 als übergabe. viel viel. hab mir gar nicht überlegt, wozu. also wenn ich neben dem objekt ne bounbding-box mitgeben kann, aber nicht muß. die default-bounding-box ist =0 und im tracercode steht allenthalten if(bb==0)...else...
oder ich mach ein sinnvolles default-argument, die globale boundingbox, die grundsätzlich "jup, der strahl schneidet ich" behauptet. bräuchte kein if mehr im tracercode.
ich kann mich gerade nicht erinnern, mal 0 als übergabe zugelassen zu haben.Zeiger koennen euren Programmen bei geschickter Nutzung zu brutaler Geschwindigkeit verhelfen.
da kann man zu 99% statt zeigern auch referenzen nehmen mit gleicher steigerung.
Klar, fuer operatoren-ueberladung, catchen, copy c'tor & co. sind Referenzen noetig.
Ich nutze Referenzen quasi nie ausser bei letzterem.das ist fein. weiter so.
Aber ausserdem gibt es keine Referenz-Arithmetik...

spricht für referenzen. aber ist zum glück nix schlimmes.
-
Mir zeigt meine IDE recht zuverlässig an welche Parameter eine Funktion erwartet. Insofern brauche ich keine Kennzeichnung und kann mich weiterhin darauf besinnen Referenzen einzusetzen wo sie Sinn machen. Überall Referenzen zu benutzen ist natürlich auch Quatsch! Manches geht eben mit den "guten alten" Pointern besser/einfacher.