Codewartung: Rohes C-Style-Array zu std::vector



  • Hallo allerseits,

    Wir müssen gerade eine aaaalten Code überholen (und um Funktionen erweitern) und wollen hierbei alte rohe C-Style-Arrays wie

    int iArray[1000];
    

    einfach auskommentieren und ersetzen durch:

    //int iArray[1000];
    std::vector<int> iArray(1000);
    

    ohne andere Codestellen zu verändern. Da ja ohnehin nur der []-Operator verwendet wurde, sollte das doch keine Problem sein, oder 😕

    Viele Grüße



  • Wäre es zu viel Aufwand, die Grösse dynamisch anzupassen? Sonst bringt der std::vector nämlich nicht allzu viel.

    Wenn das nicht drin liegt, könntest du auch statt T array[N] ein std::array<T, N> nehmen, sofern der Compiler das unterstützt. Da ist die Semantik genau gleich wie bei Arrays, aber du hast nützliche Funktionen wie size() und im Debug-Modus Index-Checks.

    Wo du aufpassen musst, ist bei impliziten Konvertierungen zu Zeigern. Dieser Code wird mit STL-Containern nicht mehr funktionieren.

    void function(int* array, int size);
    
    int x[1000];
    function(x, 1000);
    


  • Nexus schrieb:

    Wo du aufpassen musst, ist bei impliziten Konvertierungen zu Zeigern. Dieser Code wird mit STL-Containern nicht mehr funktionieren.

    void function(int* array, int size);
    
    int x[1000];
    function(x, 1000);
    

    nicht mehr im allgemeinen, in einzelfällen schon.

    gerade vector garantiert ja, dass die elemente hintereinander im speicher liegen:

    void function(int* array, int size);
    
    int x[1000];
    function(x, 1000);
    
    std::vector<int> v(1000);
    function(&v[0], v.size());
    


  • Skym0sh0 schrieb:

    nicht mehr im allgemeinen, in einzelfällen schon.

    Nein. Es existiert keine implizite Konvertierung von std::vector<T> nach T* .

    Klar kann man sich einen Zeiger auf das erste Element holen, aber dazu muss eben Code angepasst werden. Daher "Dieser Code wird mit STL-Containern nicht mehr funktionieren".



  • Nein. Es existiert keine implizite Konvertierung von std::vector<T> nach T*.

    Ja, er muss vector::data() aufrufen.

    ohne andere Codestellen zu verändern.

    Nein, das geht nicht.



  • ja ok, nexus, da hast Recht.
    Da hab was falsch verstanden.



  • Ok, danke euch schon mal für die Hinweise. Ich sehe schon, da ist mehr Arbeit nötig als gedacht (aber es hält sich noch in Grenzen) - besonders auf die implizite Konvertierung von Zeigern müssen wir hier wohl unser Augenmerk legen müssen. Wir werden entweder jetzt das Array dynamisch machen 😞 oder eben den Code etwas mehr erneuern als uns lieb ist 🙄

    Vielen Dank nochmals



  • Einfach nur die Arrays zu ersetzen bringt überhaupt nichts. Im besten Fall hat man das gleiche mit zusätzlichen Array-bound-checks, wo aber die Exceptions nicht abgefangen werden.
    Man muss schon die verbesserte Funktionalität nutzen und Funktionen, wie z.B.

    void array_push(int* array, int* size, int value);
    

    durch entsprechende Methoden ersetzen.



  • Ich push das ganze hier mal, weil ich gerade auch so etwas in der Art mache.
    Nachdem ich in mühseliger Arbeit alle Deklarationen (ist das der Plural?) ersetzt habe, musste ich feststellen, dass folgender Code nicht geht:

    std::array<int, 10> arr = { 1, 2,... };
    

    Warum gibt es für std::array keine Konstruktoren?
    Ich mein, dass ist ja schön echt wie in C, aber nerven tut es trotzdem.
    Warum fehlen die? Oder bin ich einfach nur zu blöd und die Referenz nicht richtig?
    lg
    Nathan



  • Hast du das mal ausprobiert? array hat keine Konstruktoren, weil's als Aggregat-Typ keine braucht. https://ideone.com/viD5mr



  • Nanu? 😮 Da habe ich ja komplett was übersehen...
    OK, irgendwas habe ich falsch gemacht.
    Naja, mittlerweile habe ich ein Problem hier, wo ich einen Vektor durch ein Array ersetzt habe:

    void func(std::array<int, 2> object);
    //...
    func({2, 3}); // geht nicht
    

    Mit Vektoren klappts wunderbar.



  • In dem Fall ist das keine Aggregat-Initialisierung, wie wir sie aus C kennen, sondern das C++11-Feature Initializer Lists. Da std::array keine Konstruktoren hat, kann es auch nicht von einer std::initializer_list konstruiert werden.

    Ist eine etwas spezielle Entscheidung des Standardkommitees. Liegt wahrscheinlich daran, dass es boost::array und std::tr1::array schon Jahre vor C++11 gegeben hat.


Anmelden zum Antworten