Static Function - werden daten alloziert oder nicht?



  • Folgender Code ist gegebe:

    #include <vector>
    
    struct data
    {
        std::vector<int> vec1;
        std::vector<int> vec2;
        std::vector<int> vec3;
        std::vector<int> vec4;
    };
    
    struct foo
    {
        static data& get_data()
        {
            static data my_data;
            return my_data;
        }
    };
    
    int main()
    {
        auto func = &foo::get_data;
        return 0;
    }
    

    Meine Frage lautet, wird Speicherplatz für my_data alloziert, schon wen ich den Funktionspointer abspeichere oder erst wenn ich die Funktion aufrufe?



  • Nicht-null (0x00) initialisierte statische Variablen kommen in das .data Segment des Programmes IIRC. Speicherplatz ist also im Vorhinein schon reserviert. Initialisierung (= Konstruktoraufruf) geschieht aber erst beim ersten Aufruf deiner Funktion.



  • Der Speicher wird in der globals-Sektion des Executables reserviert (jedenfalls auf gängigen Systemen), der beim Programmstart in den RAM kopiert wird. Die Konstruktoren werden allerdings erst beim ersten Aufruf der Funktion durchlaufen.



  • ich habs mal unter linux durchlaufen lassen:

    std::cout << sizeof(data) << std::endl;
    
    Ausgabe: 48 byte.
    

    Das heißt dafür werden 48 byte im data segment reserviert?


  • Mod

    someone_ schrieb:

    Das heißt dafür werden 48 byte im data segment reserviert?

    Wofür? data ist bei dir der Bezeichner für eine Klasse von Daten. Instanzierungen dieser Klasse, sofern es welche gibt, würden 48 Byte in dem entsprechenden Bereich belegen. Der Bezeichner "data" selbst existiert zur Laufzeit gar nicht.



  • okay, dann meine nächste Frage, wieviel Speicher wird reserviert?



  • SeppJ hat die Frage nicht im Kontext des Eingangspostings beantwortet. Für die Ausgabe der Größe mit sizeof wird natürlich kein Speicher reserviert.

    Im Programm aus dem Eingangsposting werden 48 Bytes in der data-Section (oder wie auch immer das auf der entsprechenden Plattform heisst) des Executables reserviert.



  • @LordJaxom
    das hast du falsch verstanden. Natürlich wird bei der sizeof expression kein speicher irgendwo reserviert.
    Ich meinte im data segment, wird sizeof(data) bytes reserviert.

    Wenn das der Fall ist, sollte folgende code speicher effizienter sein:

    #include <vector>
    #include <iostream>
    #include <memory>
    
    struct data
    {
        std::vector<int> vec1;
        std::vector<int> vec2;
        std::vector<int> vec3;
        std::vector<int> vec4;
    };
    
    struct foo
    {
        static data& get_data()
        {
        	static std::unique_ptr<data> obj = std::make_unique<data>();
        	return *obj.get();
        }
    };
    
    int main()
    {
        auto func = &foo::get_data;
        std::cout << sizeof(data) << std::endl;
        std::cout << sizeof(std::unique_ptr<data>) << std::endl;
    
        return 0;
    }
    

    Sollte wohl genauso noch thread safe sein, wie der erste code.



  • Warum?



  • Weil der speicher für die variable obj nur 4, bzw. 8 byte groß ist?



  • someone_ schrieb:

    Weil der speicher für die variable obj nur 4, bzw. 8 byte groß ist?

    Und für das data-Objekt fällt keiner mehr an?



  • Du hast es erfasst, korrekt.

    Im pointer fall wird nur der speicher für den unique_ptr reserviert nicht für data. Erst wenn ich die Funktion get_data() aufrufe, wird speicher dafür verbraucht.



  • Achso, und der Vorteil liegt quasi auf der Hand, ich verstehe.



  • Wenn die Funktion natürlich nie aufgerufen wird und Dir 48 Bytes das Genick brechen, dann ist der letzte Code natürlich hypereffizient. Noch effizienter wäre dann natürlich, die Funktion ganz weg zu lassen *hust*.


Anmelden zum Antworten