Rückgabe von Objekten



  • jo das natürlich noch besser.
    glaub das hat ja was zutun mitm default ctor.



  • bueffel schrieb:

    jo das natürlich noch besser.
    glaub das hat ja was zutun mitm default ctor.

    kaum. ja, er wird bei der aktion aufgerufen, aber darum gehts nicht.

    ohne das siehts so aus:

    Connection* function(int param) { 
           Connection *con=675;//zufälliger inhalt
           con->server("sex.com"); 
           return con; 
    }
    

    und auf adresse 675 im speicher darfst du gar nicht zugreifen. dein programm stürzt ab.
    mit new besorgst du dir den speicher.

    Connection *con=675;//zufälliger inhalt
    con=new Connection;
    

    jetzt zeigt con auf guten speicher, wo du auch draf arbeiten darfst.



  • hm. stimmt okay. irgendwie logisch.
    du kannst gut erklären, danke! 🙂

    ich hab mal gelesen von einer objekterzeugung wo man direkt aufn default ctor drauf zugreift und von einer wo man das nicht tut. irgendwie so gabs da mal was. bin vergesslich lol 🙂


  • Administrator

    Gäbe ja eigentlich noch eine weitere Möglichkeit, erst recht bei Objekten, welche nicht kopierbar sind:

    void function(Connection& con, int param)
    {
      // Wähle dank param was aus, oder was du auch mit param machen willst.
      con.server("google.com");
    }
    
    // ... irgendwo, wo du die Funktion aufrufst ...
    Connection con;      // erstelle das Objekt
    function(con, 645);  // übergib das Objekt zur Bearbeitung.
    

    Grüssli



  • Dravere schrieb:

    Gäbe ja eigentlich noch eine weitere Möglichkeit, erst recht bei Objekten, welche nicht kopierbar sind:

    Connection con;      // erstelle das Objekt
    function(con, 645);  // übergib das Objekt zur Bearbeitung.
    

    die viel sicherer, weil da kein speicherloch entstehen kann, weil man das zugehörige delete nicht vergessen kann.

    aber noch lieber mag ich dann

    Connection con;      // erstelle das Objekt
    function(&con, 645);  // übergib das Objekt zur Bearbeitung.
    

    damit ich sofort erkenne, daß con verändert wird. mir hilft das bei der fehlersuche, besonders, wenn der code schon ne ecke älter ist.


  • Administrator

    volkard schrieb:

    aber noch lieber mag ich dann

    Connection con;      // erstelle das Objekt
    function(&con, 645);  // übergib das Objekt zur Bearbeitung.
    

    damit ich sofort erkenne, daß con verändert wird. mir hilft das bei der fehlersuche, besonders, wenn der code schon ne ecke älter ist.

    Kann man das sofort erkennen? Was ist, wenn das folgende als Funktionsprototyp steht:

    void function(Connection const* con, int param);
    

    Ich finde so einen Code eher fehleranfällig und unhandlich, erst recht um die Funktion zu implementieren, da man eine Fehlerbehandlung einführen muss, falls ein Null-Zeiger übergeben wird. Und was für einen Fehler macht man dann? Assertion, Exception, Return Wert, ignorieren?

    Wenn man ein gültiges Objekt übergeben muss, dann sollte man wohl bei einer Referenz bleiben. So muss der Aufrufer dafür sorgen, dass immer ein gültiges Objekt kommt, wodurch dieser womöglich optimieren kann, da er weiss, dass nie ein ungültiges Objekt übergeben wird. Dadurch fällt die ganze Fehlerbehandlung weg.

    Grüssli

    PS: Sorry, wenn das ein wenig ins Off-Topic geht. Aber ich wäre noch gespannt auf eine Antwort darauf. 🙂



  • volkard schrieb:

    aber noch lieber mag ich dann

    Connection con;      // erstelle das Objekt
    function(&con, 645);  // übergib das Objekt zur Bearbeitung.
    

    damit ich sofort erkenne, daß con verändert wird. mir hilft das bei der fehlersuche, besonders, wenn der code schon ne ecke älter ist.

    Nachteil hierbei ist aber das eine NULL-Prüfung erfolgen muss, die wieder zu einem Fehler führen kann.

    Ich für meinen teil ziehe hier entweder:
    a) Die Referenzübergabe (Da keine Null-Werte zulässig)
    oder
    b) Eine Rückgabe eines Smartpointers (Freigabe geregelt)
    vor.

    cu André



  • Dravere schrieb:

    da man eine Fehlerbehandlung einführen muss, falls ein Null-Zeiger übergeben wird.

    nö, gar nicht. allerhöchstens ein kleines assert(con). ist doch logisch, daß das subjekt nicht 0 sein darf.


  • Administrator

    volkard schrieb:

    nö, gar nicht. allerhöchstens ein kleines assert(con). ist doch logisch, daß das subjekt nicht 0 sein darf.

    Wieso soll das logisch sein? Wenn ein Zeiger erwartet wird und wir nicht in C sind, dann ist es für mich logisch, dass man auch einen Nullzeiger übergeben kann.

    Und über dass assert(con) wird sich der Benutzer freuen, wenn zur Laufzeit ein Fehler passiert, weil er dachte, dass man auch einen Nullzeiger übergeben darf.
    Noch lustiger wird es, wenn im Debugmodus irgendwie der Fehler nie erreicht wurde, da immer ein gültiges Objekt übergeben wurde. Release erstellt, an den Kunden ausgeliefert. Der Arbeitet und plötzlich -> Fatal Error oder sonst ein Fehler, da auf einen Nullzeiger zugegriffen wurde. Alle Daten verloren ...

    Grüssli



  • volkard schrieb:

    nö, gar nicht. allerhöchstens ein kleines assert(con). ist doch logisch, daß das subjekt nicht 0 sein darf.

    Nein, Ein Zeiger impliziert auch das man 0 verwenden darf.
    Ich schaue doch nicht in die Implementierung um zu sehen ob 0 zulässig ist oder nicht. Bei der Referenzübergabe geht es garnicht anders, und hier muss man nur die Deklaration kennen um sauber zu programmieren!

    cu André



  • asc schrieb:

    Nein, Ein Zeiger impliziert auch das man 0 verwenden darf.

    nö. die spracher erlaubt es. aber das ist auch schon alles.
    bevor du weiter sowas sagst, würde ich gerne wissen, was gibt strlen(0) eigentlich zurück?



  • volkard schrieb:

    nö. die spracher erlaubt es. aber das ist auch schon alles.
    bevor du weiter sowas sagst, würde ich gerne wissen, was gibt strlen(0) eigentlich zurück?

    Keine Ahnung, da ich C-Funktionen nur dann einsetze wenn C++ wirklich ein Flaschenhals in der Anwendung ist, oder begrenzt an DLL-Schnittstellen. Und ersteres habe ich bislang nur äußerst selten im Praxiseinsatz erlebt.

    P.S: Und Diskussionen über C-Schnittstellen wären glaube ich eher im C-Forum passend, oder?


  • Administrator

    volkard schrieb:

    bevor du weiter sowas sagst, würde ich gerne wissen, was gibt strlen(0) eigentlich zurück?

    Wenn ich da auch noch was hinzufügen darf neben den Argumenten von asc.
    Seit wann hat die Sprache C:
    a) Referenzen? Daher ist es ziemlich witzig, dass du eine C Funktion nennst.
    b) Klassen? Man kann einen String in C gar nicht anders als über einen Zeiger implementieren.

    Wie es asc gesagt hat, wir sind hier im C++ Forum.

    Grüssli



  • sie schmiert ab. und das ist nicht schlimm. so grobe programmierfehler muss keiner fangen.



  • Dravere schrieb:

    Wieso soll das logisch sein? Wenn ein Zeiger erwartet wird und wir nicht in C sind, dann ist es für mich logisch, dass man auch einen Nullzeiger übergeben kann.

    Bevor ich so eine "Logik" anwende, würde ich mich über die Preconditions der Funktion schlaumachen.

    Und über dass assert(con) wird sich der Benutzer freuen, wenn zur Laufzeit ein Fehler passiert, weil er dachte, dass man auch einen Nullzeiger übergeben darf.

    Seit wann übergeben Benutzer Nullzeiger? Das wird schon noch ein anderer Programmierer gewesen sein, und zwar einer, der eher obige "Logik" bevorzugt.

    C-Funktionen

    Dann nimm halt eine C++-Funktion, die einen char-Pointer erwartet. Den Konstruktor von ifstream z.B.



  • Bashar schrieb:

    Dravere schrieb:

    Wieso soll das logisch sein? Wenn ein Zeiger erwartet wird und wir nicht in C sind, dann ist es für mich logisch, dass man auch einen Nullzeiger übergeben kann.

    Bevor ich so eine "Logik" anwende, würde ich mich über die Preconditions der Funktion schlaumachen.

    Die meisten Referenzen die ich kenne, erwähnen diese nicht. Davon ganz abgesehen:

    Wenn man die Preconditions bereits an der Deklaration erkennt, halte ich dies für eine bessere Wahl, als das man erst einmal die Dokumentation suchen muss.

    Bashar schrieb:

    C-Funktionen

    Dann nimm halt eine C++-Funktion, die einen char-Pointer erwartet. Den Konstruktor von ifstream z.B.

    Es gibt einen guten Grund warum die C++Funktionen im kommenden Standard in diesen Punkt umgestellt werden.



  • asc schrieb:

    Wenn man die Preconditions bereits an der Deklaration erkennt, halte ich dies für eine bessere Wahl, als das man erst einmal die Dokumentation suchen muss.

    für mich ist const/nichtconst ein viel wichtigerer punkt, den ich ohne doku wissen will, als null/nichtnull.
    die versehentliche annahme, ein objekt werde nicht verändert, kann für viel längere suchzeiten sorgen, als die versehentliche verwendung der 0. vorausgesetzt, daß man einen debugger hat. und die const/nichtconst-fehlannahmen kommen häufiger vor, hab ich das gefühl. daher bevorzuge ich meine "Logik" und die verträgt sich einfach nicht mit eurer. mir scheint, eure enstand aus einem unverständnis und im informationsvakuum hat man sich dummerweise am verbot von nullreferenzen festgehalten und verasucht, damit eine fehlervermeidende regel zu basteln. meyers gelesen und auch mal meyers sein wollen. und sich keine gedanken gemacht, was wirklich fehler vermeidet.



  • volkard schrieb:

    Dravere schrieb:

    da man eine Fehlerbehandlung einführen muss, falls ein Null-Zeiger übergeben wird.

    nö, gar nicht. allerhöchstens ein kleines assert(con). ist doch logisch, daß das subjekt nicht 0 sein darf.

    Hmmmm ... mal eine etwas andere Frage: Anhand wessen sollte man sich überhaupt zwischen Zeigern oder Referenzen unterscheiden?

    Mein persönliches Kriterium war bislang immer: "Ist es nullable oder verschiebbar, nimm Zeiger; sonst Referenz."
    (Was nicht bedeutet, dass das das beste/einzige/sinnvollste/... Kriterium sei - eben nur mein(bisherige)s).

    Ob es sich um einen Input- oder einen update-Parameter handelt, würde ich persönlich nur anhand der Schnittstelle (const oder non-const; gilt für Zeiger genauso wie für Referenzen) entscheiden ...

    Gruß,

    Simon2.



  • asc schrieb:

    Die meisten Referenzen die ich kenne, erwähnen diese nicht.

    Schön, aber was willst du damit ausdrücken? Dass du nichts von der Dokumentation von Kontrakten hältst oder wie?

    Wenn man die Preconditions bereits an der Deklaration erkennt, halte ich dies für eine bessere Wahl, als das man erst einmal die Dokumentation suchen muss.

    Man erkennt leider nicht an der Deklaration, ob Nullzeiger erlaubt sind oder nicht. Ansonsten siehe volkard.

    Bashar schrieb:

    Dann nimm halt eine C++-Funktion, die einen char-Pointer erwartet. Den Konstruktor von ifstream z.B.

    Es gibt einen guten Grund warum die C++Funktionen im kommenden Standard in diesen Punkt umgestellt werden.

    Und du meinst, der Grund wäre, dass die Leute sich nicht darüber im klaren sind, dass man da keinen Nullzeiger übergeben darf? Du weichst der Frage aus.



  • Simon2 schrieb:

    Mein persönliches Kriterium war bislang immer: "Ist es nullable oder verschiebbar, nimm Zeiger; sonst Referenz."

    Meins ist: Referenzen nur wenns const-Referenzen sein können, also nur zum unsichtbaren beschleunigen.

    Allerdings kommt die Frage ja eh nur sehr selten auf und wird mit der Zeit immer seltener. Die Connection zum Beispiel wird vermutlich einen Konstruktor haben, der connected.


Anmelden zum Antworten