Zeiger oder Referenz



  • Ich bin _nicht_ Volkards Meinung, denn bei nem Zeiger solltest du noch auf != 0 überprüfen, was du dir bei Referenzen sparen kannst. Zudem ist ein add( vec ); kürzer als ein add( &vec );

    Ich nehme pointer nur, wenn ich wirklich muss.



  • volkard schrieb:

    besser sind hier zeiger, um beim aufruf schon zu zeigen, daß was geändert wird an den daten. nimm die referenz, wenn sie als const-referenz geht, also eigentlich auch by-value gehen würde, und wenn es sich wie mit by-value anfühlen soll.

    Mit dieser Meinung bist du hier ziemlich alleine!



  • swap. schrieb:

    Mit dieser Meinung bist du hier ziemlich alleine!

    irgend jemand muß ja vorangehen. wir haben lange zeit zu viele referenzen benutzt aus fadenscheiniten gründen, eigentlich nur, weil es geht. du wirst oft hören "nimm immer referenzen, wenn es überhaupt möglich ist und nur im aüßerseten notfall zeiger". aber selten mit guter begründung und nie mit einer, die einer längeren diskussion standhält. weil es nämlich gar nicht so ist, daß man bei zeigern jeden übergebenen wert auf 0 prüfen sollte.



  • volkard schrieb:

    swap. schrieb:

    Mit dieser Meinung bist du hier ziemlich alleine!

    irgend jemand muß ja vorangehen. wir haben lange zeit zu viele referenzen benutzt aus fadenscheiniten gründen, eigentlich nur, weil es geht. du wirst oft hören "nimm immer referenzen, wenn es überhaupt möglich ist und nur im aüßerseten notfall zeiger". aber selten mit guter begründung und nie mit einer, die einer längeren diskussion standhält. weil es nämlich gar nicht so ist, daß man bei zeigern jeden übergebenen wert auf 0 prüfen sollte.

    Du glaubst du gehst voran ? Aber nur weil du dich nicht umdrehst und siehst
    das alle anderen in die entgegengesetzte Richtung marschieren. 😃 😃



  • m.E. gehoeren Zeiger nur dort hin, wo man sie absolut nicht vermeiden kann.

    Referenzen sind aus vielerlei Hinsicht besser: Sie bringen das Fehlerrisko nahe Null, machen den Code lesbarer, und sind fuer den Compiler leichter zu optimieren (da der Geltungsbereich genau definiert ist).

    Falls moeglich, sollte man nur Zeiger verwenden, die die Adresse einer Referenz nehmen (z.B. bei Konstruktorparametern).

    Am besten ist, man vermeidet auch new- und delete-Operator-Aufrufe. Man kann in C++ ja Objekte auf dem Stack deklarieren, die dann beim Verlassen des Geltungsbereichs automatisch vernichtet werden. Das nicht nur praktisch, sondern auch lesbarer, und bei der Exception-Behandlung muss man sich dann auch um nichts kuemmern.

    Manche Leute verwenden gruendsatzlich nur dieses Modell, und verwenden Zeiger nur innerhalb von AutoPointer-Objekten.

    Referenzen helfen, C++ Code robust zu machen.

    Setzt man Referenzen geschickt ein, kann man in C++ genauso idiotensicher wie z.B. in Java programmieren.



  • Hoffentlich artet das nicht in Streit aus. 😞

    volkard hat sowieso Unrecht.



  • Meine bescheidene Laienmeinung tut hier sicher nichts zur Sache, weswegen ich sie nicht kundtun werde, jedoch möchte ich darauf hinweisen, dass Volkard nicht ganz so "alleine" steht wie, behauptet wurde. Stroustrup sagt in "The C++ Language" das selbe unter Anführung gleicher Gründe (S. 107 deutsch, Ausgabe 4).

    Zum Überprüfen der Zeiger auf 0: Weiter oben angeführte C++-FAQ impliziert ähnliches in anderem Kontext: http://www.parashift.com/c++-faq-lite/exceptions.html#faq-17.12

    (Kurz: dass eine Überprüfung auf 0 von Zeiger-Argumenten nicht immer notwendig ist.)



  • Konrad Rudolph schrieb:

    (Kurz: dass eine Überprüfung auf 0 von Zeiger-Argumenten nicht immer notwendig ist.)

    Eine Referenz ist kein Zeiger, daher hinkt der Vergleich (falls beabsichtigt).

    Die Ueberpruefung von Zeigern auf 0 bringt relativ wenig, da der Fall selten vorkommt, dass ein falscher Zeiger auf die Adresse 0 zeigt.

    Ausnahme sind z.B. ungepruefte dynamic_cast<> Aufrufe, sowie andere Aufrufe, die einen 0-Zeiger im Fehlerfall zurueckliefern, der dann ungeprueft als Zeiger verwendet wird. D.h. die Pruefung sollte beim Aufrufer erfolgen und nicht beim Aufgerufenen.

    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.

    Aber man kann sich dann gleich fragen lassen, warum man C++ und nicht C benutzt. Der Programmieroverhead in C++ wird durch die Verwendung von Zeigern stark erhoeht, und das Fehlerrisiko steigt.



  • Power Off schrieb:

    Konrad Rudolph schrieb:

    (Kurz: dass eine Überprüfung auf 0 von Zeiger-Argumenten nicht immer notwendig ist.)

    Eine Referenz ist kein Zeiger, daher hinkt der Vergleich.

    Ich bezog mich auf Volkards Aussage "[...] weil es nämlich gar nicht so ist, daß man bei zeigern jeden übergebenen wert auf 0 prüfen sollte."

    Der Programmieroverhead in C++ wird durch die Verwendung von Zeigern stark erhoeht, und das Fehlerrisiko steigt.

    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).



  • 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
    

Anmelden zum Antworten