Pointer auf Variable in deren Initialisierung benutzen



  • Hallo,

    ich habe ein paar Fragen bezüglich folgendem Code (nachdem diese Nebenfrage in meinem anderen Thread wohl etwas untergegangen ist):

    #include <iostream>
    
    struct Test
    {
        int do_something(int *i_ptr)
        {
            this->i_ptr = i_ptr;
            return 0;
        }
        int i = do_something(&i); // <- Ok?
        int *i_ptr;
    };
    
    int main()
    {
        Test test;
        std::cout << *(test.i_ptr) << '\n';
    }
    

    Ist das überhaupt erlaubt die Addresse von i in dessen Initialisierung zu benutzen oder ist das eventuell UB?

    Ich frage weil es unter VS2008 nicht kompiliert, dort bekomme ich die folgenden Fehlermeldungen:

    `

    error C2065: 'i' nichtdeklarierter Bezeichner

    error C2864: "Test::i": Nur statische konstante integrale Datenmember können innerhalb einer Klasse initialisert werden.

    `

    Unter ideone.com mit C++14 kompiliert es aber anstandslos und gibt auch das erwartete Ergebnis (0) aus.

    Wer hat jetzt recht? Oder verwendet der Code hier irgendwelche neuen C++11/C++14 Features die diese Art der Initialisierung erlauben?



  • Non-static data member initializers wurden mit C++11 eingeführt (Mit VS2008 hast du da also keine Chance). So wie in deinem Code habe ich das bisher noch nicht gesehen, aber denke es ist erlaubt. IMHO ist diese Schreibweise identisch (bis auf eventuelle Ausnahmen) zu:

    struct Test
    {
        int do_something(int *i_ptr)
        {
            this->i_ptr = i_ptr;
            return 5;
        }
        int i;
        int *i_ptr;
    
        Test()
          : i(do_something(&i))
        {
        }
    };
    


  • sebi707 schrieb:

    Non-static data member initializers wurden mit C++11 eingeführt (Mit VS2008 hast du da also keine Chance).

    Ah ok, das erklärt zumindest das. Ist aber auch kein Problem, weil ich das eh nur auf einem C++11 Compiler brauche, hatte mich nur gewundert dass es in VS nicht geht.

    sebi707 schrieb:

    So wie in deinem Code habe ich das bisher noch nicht gesehen, aber denke es ist erlaubt. IMHO ist diese Schreibweise identisch (bis auf eventuelle Ausnahmen) zu:

    Hm, was denn für Ausnahmen?

    Die Version mit dem Konstruktor kann ich halt nicht verwenden (aus Macro-technischen Gründen).



  • happystudent schrieb:

    Hm, was denn für Ausnahmen?

    Die Version mit dem Konstruktor kann ich halt nicht verwenden (aus Macro-technischen Gründen).

    Mir sind keine Ausnahmen bekannt und ich habe gerade auch keinen Absatz aus dem Standard parat, daher habe ich es zur Sicherheit hingeschrieben. Das Beispiel mit dem Konstruktor sollte zeigen warum der Code wohl korrekt ist. In der Member Initializer List kann ich Memberfunktionen aufrufen also sollte das auch bei deiner Variante auch funktionieren.



  • sebi707 schrieb:

    Mir sind keine Ausnahmen bekannt und ich habe gerade auch keinen Absatz aus dem Standard parat, daher habe ich es zur Sicherheit hingeschrieben. Das Beispiel mit dem Konstruktor sollte zeigen warum der Code wohl korrekt ist. In der Member Initializer List kann ich Memberfunktionen aufrufen also sollte das auch bei deiner Variante auch funktionieren.

    Ok gut, alles klar 👍


  • Mod

    Ist das überhaupt erlaubt die Addresse von i in dessen Initialisierung zu benutzen oder ist das eventuell UB?

    Es ist erlaubt ([basic.life]/5). Sogar die Zuweisung ist erlaubt, denn die Lebenszeit eines Skalars beginnt, sobald der zugehörige Speicher alloziert wurde ([basic.life]/(1.1 w/o 1.2). Selbstverständlich gelten andere Regeln, sobald du int durch etwas ersetzt, das non-vacuous initialization hat.


Anmelden zum Antworten