Größe eines zweidimensionales Arrays innerhalb der Laufzeit definieren



  • Hi,

    Ich habe ein relativ simples Problem: Ich weiß wie man die Größe eines eindimensionalen arrays während der Laufzeit bestimmen kann (mit "int *array = new int [groesse]"), jedoch funktioniert dies in der gleichen Form bei zweidimensionalen arrays nicht (bzw. ich weiß nicht wie). Mein Ansatz:

    int groesse;
    	cout << "Matrizengroesse: ";
    	cin >> groesse;
    	int *matrix = new int [groesse] [groesse];
    	for (int i = 0; i<groesse; i++){
    		for (int k = 0; i<groesse; i++){
    			cin >> matrix [i] [k];}}
    

    Für Zeile 4 bekomme ich folgende Fehlermeldung: [Error] 'groesse' cannot appear in a constant-expression
    Und für Zeile 7: invalid types 'int[int]' for array subscript
    Mit den beiden Meldungen fang ich als Laie jedoch nichts an 🙄
    Ist mein genereller Ansatz (also auch für eindimensionale) falsch oder gibt es bei zweidimensionalen etwas besonderes zu beachten?
    Schonmal danke im Voraus für Antworten! 😃



  • So ein Sprachkonstrukt gibt es nicht. Du musst groesse*groesse Elemente anfordern und dann selber die Indizes beim Zugriff umrechnen.
    Nimm dafür aber unbedingt std::vector<int> und nicht new .



  • finde es bescheuert dass es nicht geht.
    kannst aber [groesse] int* pointer anfordern und jedem dieser Elemente dann new int[groesse] zuweisen.



  • randa schrieb:

    finde es bescheuert dass es nicht geht.

    Wäre sprachtechnisch nicht so einfach abzuhandeln. Du hast auf einmal unvollständige Typen an Stellen, wo du sie nicht erwartest. Angenommen, ich schreibe zum Beispiel

    template<std::size_t N>
    void do_stuff_with_2d_array(T (*ptr)[N]) {
      ...
    }
    
    ...
    
    // Angenommen, es gäbe VLAs in C++.
    int (*foo)[bar] = new int[foo][bar];
    do_stuff_with_2d_array(foo);
    

    ...was soll dann passieren? Oder auch:

    std::enable_if<std::is_same<decltype(foo), int (*)[10]>::value, int>::type bar;
    

    VLAs in C++ einzupflegen ist ungleich schwerer, als es in C der Fall war.

    Zudem ist es nicht so richtig notwendig. Wenn du nackte 2D-Arrays mit new anforderst, machst du sowieso etwas falsch, und es gibt genug andere Wege, das Problem in einer Weise zu erschlagen, die ohne drei Seiten Boilerplate exceptionsicher wird. Ganz billige Methode:

    template<typename T>
    class array2d {
    public:
      array2d(std::size_t y, std::size_t x) : data_(x * y), x_(x) { }
    
      T       *operator[](std::size_t y)       { return &data_[y * x_]; }
      T const *operator[](std::size_t y) const { return &data_[y * x_]; }
    
    private:
      std::vector<T> data_;
      std::size_t x_;
    };
    
    ...
    
    array2d<int> foo(bar, baz);
    
    foo[0][1] = 2;
    

    Bessere Möglichkeiten finden sich zum Beispiel in Boost.Multi-Array oder (für Matrixrechnung) Eigen. Ansonsten tut's oft auch ein std::vector<std::vector<int>>.


Anmelden zum Antworten