Lebensdauer Default-Argumente



  • Hi,

    ist dies definiert und gültig:

    class A 
    { 
        private:
                    char * aa; 
        public: 
                    A( char *t  = "hhh" ) : aa(t) {}
    };
    

    Schließlich müsste das temporäre Objekt nachm Konstruktordurchlauf zerstört werden und aa in Nirvana zeigen ...

    Was sagt der Standard dazu ?

    Edit:
    Bessere Alternative wäre dies hier:

    char * defValue()
    {
        static char * t = "hhh";
        return t;
    }
    // ...
     A( char *t  = defValue() ) : aa(t) {}
    

    ... ja, std::string verwenden, es geht mir aber ums Verhalten von C++ in diesem Fall.



  • aa zeigt nicht auf das temporäre Objekt, sondern auf das Stringliteral "hhh" (worauf das temporäre Objekt auch gezeigt hat). Stringliterale haben statische Speicherdauer.



  • Bashar schrieb:

    Stringliterale haben statische Speicherdauer.

    Danke für die Antwort, jetzt ist mir alles klar 🙂



  • Und wie siehts mit "normalen Default-Objekten" aus ? (also ohne static Membern)

    Gruß,

    Simon2.


  • Mod

    Hier ist weit und breit kein temporäres Objekt in Sicht.



  • camper schrieb:

    Hier ist weit und breit kein temporäres Objekt in Sicht.

    DAS hatte Bashar auch schon entdeckt. 😉

    OK, also meine Frage mal mit Code:
    1.)

    void f(std::string& s = std::string("Simon2"));
    

    Haben wir hier ein temporäres Objekt ? Wenn ja: Wie lange lebt es ?

    2.)
    Wie sieht die Situation bei

    void f(std::string const& s = std::string("Simon2"));
    

    aus ?

    3.)
    Wird bei

    void f(std::string s = std::string("Simon2"));
    

    noch eines erzeugt und s per CpyCtor konstruiert ? Darf der Compiler die Konstruktion ggf. "abkürzen" ?

    Gruß,

    Simon2.



  • Zu 1.) und 2.) gab es die Tage schonmal folgendes in http://c-plusplus.net/forum/viewtopic-var-t-is-210594.html

    camper schrieb:

    Ein temporäres Objekt, dass an einen Refernzparameter eines Funktionsaufrufes gebunden wird, lebt bis zum Ende des vollständigen Ausdrucks, der den Funktionsaufruf enthält .


  • Mod

    1. ist nicht möglich.

    3.)
    Wird bei

    void f(std::string s = std::string("Simon2"));
    

    noch eines erzeugt und s per CpyCtor konstruiert ? Darf der Compiler die Konstruktion ggf. "abkürzen" ?

    ja und ja. Es gibt hinsichtlich der Auswertung keinen Unterschied zwischen einem Defaultargument und einem Funktionsaufruf, der das Argument explizit übergibt. Unterschiede bestehen lediglich im Namelookup - das spielt aber für diese Frage keine Rolle.



  • LordJaxom schrieb:

    Zu 1.) und 2.) gab es die Tage schonmal folgendes in http://c-plusplus.net/forum/viewtopic-var-t-is-210594.html

    camper schrieb:

    Ein temporäres Objekt, dass an einen Refernzparameter eines Funktionsaufrufes gebunden wird, lebt bis zum Ende des vollständigen Ausdrucks, der den Funktionsaufruf enthält .

    Das zusammen mit

    camper schrieb:

    ...Es gibt hinsichtlich der Auswertung keinen Unterschied zwischen einem Defaultargument und einem Funktionsaufruf, der das Argument explizit übergibt....

    hilft mir schon deutlich weiter.
    Noch eine Nachfrage:
    Ist

    void f(std::string& s);
    
    f(std::string("Simon2"));
    

    dann auch verboten oder hört die Analogie da auf ?

    Und nochmal zur Sicherheit:

    void f(std::string const & s = std::string("Simon2"));
    

    ist also erlaubt, ja ?

    Gruß,

    Simon2.



  • Simon2 schrieb:

    Noch eine Nachfrage:
    Ist

    void f(std::string& s);
    
    f(std::string("Simon2"));
    

    dann auch verboten oder hört die Analogie da auf ?

    Ja, ist verboten, da ein temporäres Objekt nicht an eine non-const Referenz gebunden werden kann.

    Simon2 schrieb:

    Und nochmal zur Sicherheit:

    void f(std::string const & s = std::string("Simon2"));
    

    ist also erlaubt, ja ?

    Ich denke mal ja 🙂



  • interessant wird es ja auch erst bei

    void foo (string&);
    
    foo (string() = "foo");
    

    🙂


  • Mod

    queer_boy schrieb:

    interessant wird es ja auch erst bei

    void foo (string&);
    
    foo (string() = "foo");
    

    🙂

    Interessant ist auch

    std::complex<double> a = 1, b = 2, c = 3;
    const std::complex<double>& d = a + b + c;
    const std::complex<double>& e = ( a + b ) += c;
    std::cout << d; // ok
    std::cout << e; // boom
    

Anmelden zum Antworten