Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

1

05.08.2007, 00:21

math::matrix ... was würdet ihr verbessern?

Hab letztens mal in nem Forum hier mal die kleine Klasse geschrieben ... wollte die eig. mal auf Seite legen falls ich se noch mal brauche ... auch wenn ich nicht von ausgehe ^^ Aber was solls ... also ... was würdet ihr noch ausbessern? Sollten Iteratoren rein? Wo seht ihr die Vorteile die dafür sprechen ... wie findet ihr den Codestyle ... ok ist nur ne schnell zusammengeklatschte Klasse ... vllt insg. 5 bis 10 min arbeit ... musste nochmal nachgucken wie bubblesort ging ^^

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
namespace math
{
    template <typename T>
    void bubble_sort(T*& arr, std::size_t size)
    {
        bool redo = false;
        do {
            redo = false;
            for (std::size_t i = 0; (i < (size - 1) && arr[i] != NULL && arr[i+1] != NULL); ++i)
                if (arr[i] > arr[i + 1])        { std::swap<T>(arr[i], arr[i + 1]); redo = true; }
        } while (redo == true); 
    }

    template <typename T>
    class matrix
    {
    public:
        matrix(std::size_t row = 1, std::size_t col = 1) : m_row(row), m_col(col)
        {
            m_data = new T*[row];
            for (std::size_t cur = 0; cur < row; ++cur) m_data[cur] = new T[col];
        }

        ~matrix()
        {
            for (std::size_t cur = 0; cur < m_row; ++cur) delete [] m_data[cur]; 
            delete [] m_data;
        }

        T& operator ()(std::size_t row, std::size_t col)        { return at(row, col); }
        T* operator [](std::size_t row)     { if (row > m_row) throw std::out_of_range("row"); return m_data[row];  }

    public:
        T&          at(std::size_t row, std::size_t col)    { if (row > m_row || col > m_col) throw std::out_of_range("col or row"); return m_data[row][col]; }
        T const &   min() const     {   T const & min; for (std::size_t row = 0; row < m_row; ++row) for (std::size_t col = 0; col < m_col; ++col)  min = std::min(m_data[row][col], min); return min; }
        T const &   max() const     {   T const & max; for (std::size_t row = 0; row < m_row; ++row) for (std::size_t col = 0; col < m_col; ++col)  max = std::max(m_data[row][col], max); return max; }
        std::size_t size() const    { return (m_row * m_col); }
        void        resize(std::size_t row, std::size_t col)
        {
            T** tmp_data = new T*[row];
            for (std::size_t cur_row = 0; cur_row < row; ++cur_row)
            {
                tmp_data[cur_row] = new T[col];
                for (std::size_t cur_col = 0; cur_col < col; ++cur_col) if (cur_col < m_col && m_row > cur_row) tmp_data[cur_row][cur_col] = m_data[cur_row][cur_col];
            }
            for (std::size_t cur = 0; cur < m_row; ++cur) delete [] m_data[cur]; 
            delete [] m_data;
            m_data = tmp_data;  m_row = row; m_col = col;
        }

        void        sort()          { for (std::size_t cur_row = 0; cur_row < m_row; ++cur_row) bubble_sort<T>(m_data[cur_row], m_col); }

    private:
        T**             m_data;
        std::size_t     m_row;
        std::size_t     m_col;
    };
};

int main()
{
    math::matrix<int> mat(4, 4);
    mat.at(1, 1) = mat.size();
    mat.resize(6,6);
    mat(5, 1) = 1;
    ++mat[5][1];
    return mat.at(5, 1);
}


C&C please!
Devil Entertainment :: Your education is our inspiration
Der Spieleprogrammierer :: Community Magazin
Merlin - A Legend awakes :: You are a dedicated C++ (DirectX) programmer and you have ability to work in a team? Contact us!
Siedler II.5 RttR :: The old settlers-style is comming back!

Also known as (D)Evil

David_pb

Community-Fossil

Beiträge: 3 886

Beruf: 3D Graphics Programmer

  • Private Nachricht senden

2

05.08.2007, 09:24

Habs mal überflogen und mir folgende Punkte rausgeschrieben:

:arrow: Exceptionhandling (vor allem in c'tor und bei der Methode resize)
:arrow: Konstante Versionen von operator() und operator[]
:arrow: Bei operator[] keinen Zeiger zurückgeben, lieber auf irgendein Proxyobjekt ausweichen
:arrow: Der operator[] sollte keine Ausnahme werfen. Is nur ein Vorschlag und orientiert sich an den Containerregeln der STL, aber da du dich ja ohnehin daran orientiert hast (at, iteratoren, etcpp)...
:arrow: Iteratoren könntest du mit einbauen, ich seh aber egtl keinen großen Sinn bei einer Matrixklasse.
@D13_Dreinig

3

05.08.2007, 11:24

Zitat

:arrow: Exceptionhandling (vor allem in c'tor und bei der Methode resize)
Was willst du denn noch für Exceptionswerfen? Sollte ja eigentlich nichts mehr schief gehen ... bis auf das evt. nicht genug Platz für die allocation da ist ...

Zitat

:arrow: Arrow Der operator[] sollte keine Ausnahme werfen. Is nur ein Vorschlag und orientiert sich an den Containerregeln der STL, aber da du dich ja ohnehin daran orientiert hast (at, iteratoren, etcpp)...
Hmm jap ... ist geändert ^^

Zitat

:arrow: Konstante Versionen von operator() und operator[]
Vom operator() hab ich es nun drin ... aber von [] muss ich erstmal das von wegen Proxyobjekt gucken ...

Zitat

:arrow: Iteratoren könntest du mit einbauen, ich seh aber egtl keinen großen Sinn bei einer Matrixklasse.
Die Überlegung dahinter war vielmehr, es zu vereinfachen stl-algorithm an der Klasse anwenden zu können ...

Aja ... würdest du eine Abhängigkeit zu STL-Algorithm (std::max, std::min, std::sort, std::swap) drin lassen oder schnell selbst definieren ... sind ja durchaus Funktionen die mit in einen namespace math passen würden ... bisaus std::swap ...

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#include <algorithm>
#include <stdexcept>

namespace math
{
    template <typename T>
    class matrix
    {
    public:
        matrix(std::size_t row = 1, std::size_t col = 1) : m_row(row), m_col(col)
        {
            m_data = new T*[row];
            for (std::size_t cur = 0; cur < row; ++cur) m_data[cur] = new T[col]; 
        }

        ~matrix()
        {
            for (std::size_t cur = 0; cur < m_row; ++cur) delete [] m_data[cur]; 
            delete [] m_data;
        }

        T& operator ()(std::size_t row, std::size_t col)                { return at(row, col);  }
        T const& operator () (std::size_t row, std::size_t col) const   { return at(row, col);  }
        T* operator [](std::size_t row)                                 { return m_data[row];   }

    public:
        T&          at(std::size_t row, std::size_t col)        { if (row >= m_row || col >= m_col) throw std::out_of_range("col and/or row"); return m_data[row][col]; }
        T const&    at(std::size_t row, std::size_t col) const  { if (row >= m_row || col >= m_col) throw std::out_of_range("col and/or row"); return m_data[row][col]; }
        T const &   min() const     {   T const & min; for (std::size_t row = 0; row < m_row; ++row) for (std::size_t col = 0; col < m_col; ++col)  min = std::min(m_data[row][col], min); return min; }
        T const &   max() const     {   T const & max; for (std::size_t row = 0; row < m_row; ++row) for (std::size_t col = 0; col < m_col; ++col)  max = std::max(m_data[row][col], max); return max; }
        std::size_t size() const    { return (m_row * m_col); }
        void        resize(std::size_t row, std::size_t col)
        {
            T** tmp_data = new T*[row];
            for (std::size_t cur_row = 0; cur_row < row; ++cur_row)
            {
                tmp_data[cur_row] = new T[col];
                for (std::size_t cur_col = 0; cur_col < col; ++cur_col) if (cur_col < m_col && m_row > cur_row) tmp_data[cur_row][cur_col] = m_data[cur_row][cur_col];
            }
            for (std::size_t cur = 0; cur < m_row; ++cur) delete [] m_data[cur]; 
            delete [] m_data;
            m_data = tmp_data;  m_row = row; m_col = col;
        }

        void            sort()          { for (std::size_t cur_row = 0; cur_row < m_row; ++cur_row) std::sort<T>(m_data[cur_row], m_data[cur_row] + m_col); }

    private:
        T**             m_data;
        std::size_t     m_row;
        std::size_t     m_col;
    };
};


C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <iostream>
#include "math.h"

int main()
{
    math::matrix<int> mat(4, 4);
    mat.at(1, 1) = mat.size();
    std::cout << "(1, 1): " << mat.at(1, 1) << std::endl;
    mat.resize(6, 6);
    mat(5, 1) = 1;
    std::cout << "(5, 1): " << mat.at(5, 1) << std::endl;
    ++mat[5][1];
    std::cout << "(5, 1): " << mat.at(5, 1) << std::endl;
}


Bearbeitung
- at hat row und col falsch kontrolliert! (> statt >=)
- david_pb's Aussage das new nie 0 zurückgibt wieder drin.

Werde das alloc aber noch "versichern" ;)
Devil Entertainment :: Your education is our inspiration
Der Spieleprogrammierer :: Community Magazin
Merlin - A Legend awakes :: You are a dedicated C++ (DirectX) programmer and you have ability to work in a team? Contact us!
Siedler II.5 RttR :: The old settlers-style is comming back!

Also known as (D)Evil

David_pb

Community-Fossil

Beiträge: 3 886

Beruf: 3D Graphics Programmer

  • Private Nachricht senden

4

05.08.2007, 11:44

Exceptionhandling

C-/C++-Quelltext

1
2
3
4
5
6
7
matrix(std::size_t row = 1, std::size_t col = 1) : m_row(row), m_col(col) 
        { 
            m_data = new T*[row]; 
            if (m_data == NULL) 
                throw std::bad_alloc(); 
            for (std::size_t cur = 0; cur < row; ++cur)    { m_data[cur] = new T[col]; if (m_data[cur] == NULL) throw std::bad_alloc(); } 
        }


Du sollst ja keine Ausnahmen werfen sondern abfangen. Der new Operator wirft schon selbst eine Ausnahme vom Typ std::bad_alloc(), die sollte aber behandelt werden weil du sonst Speicherleaks bekommst. Equivalent auch bei der Methode resize().
Die Abfrage ober der Resultierende Zeiger vom new Operator gleich '0' ist, ist Schwachsinn da der Fall nie zutreffen wird.

Iteratoren
Wieviele Fälle würden denn spontan einfallen wo du die Matrix durch STL Algorithmen jagen würdest? Das sollte egtl der seltenste Fall sein.

STL Algorithmen
Ich würde die Algorithmen nur austauschen wenn ich eine Bessere Variante selbiger hätte. Ich vermute mal, dass das bei dir nicht der Fall ist, warum also das Rad zweimal erfinden?

Ansonsten
Du solltest evtl noch ein wenig Funktionalität in Richtung Matheoperationen anbieten.
@D13_Dreinig

5

05.08.2007, 12:05

Zitat

STL Algorithmen
Ich würde die Algorithmen nur austauschen wenn ich eine Bessere Variante selbiger hätte. Ich vermute mal, dass das bei dir nicht der Fall ist, warum also das Rad zweimal erfinden?

Hmm ... damit weniger Header-Abhängigkeiten bestehen ... im Falle der Standardbibliothek aber sicherlich nicht nötig.

Zitat

Ansonsten
Du solltest evtl noch ein wenig Funktionalität in Richtung Matheoperationen anbieten.
Joa könnte ich dann machen wenn ich se irgendwann mal brauch ... hab die Klasse nur für einem in nem anderen Forum schnell getippt gehabt und wollte jetzt halt nur suchen was noch an Schönheitsfehlern drin ist ...

Zitat

Iteratoren
Wieviele Fälle würden denn spontan einfallen wo du die Matrix durch STL Algorithmen jagen würdest? Das sollte egtl der seltenste Fall sein.

count[_if](um bsw. bei einer matrix<int> gucken zu können wie oft 1 vorkommt), copy(falls man bsw. die Elemente einer Zeile in einen Vektor kopieren will ... warum auch immer ^^) usw. eigentlich könnte man die meisten Algorithmen dann dabei nutzen ... sicher ... es geht auch so ...
Devil Entertainment :: Your education is our inspiration
Der Spieleprogrammierer :: Community Magazin
Merlin - A Legend awakes :: You are a dedicated C++ (DirectX) programmer and you have ability to work in a team? Contact us!
Siedler II.5 RttR :: The old settlers-style is comming back!

Also known as (D)Evil

David_pb

Community-Fossil

Beiträge: 3 886

Beruf: 3D Graphics Programmer

  • Private Nachricht senden

6

05.08.2007, 13:04

Zitat von »"Deviloper"«

Zitat

STL Algorithmen
Ich würde die Algorithmen nur austauschen wenn ich eine Bessere Variante selbiger hätte. Ich vermute mal, dass das bei dir nicht der Fall ist, warum also das Rad zweimal erfinden?

Hmm ... damit weniger Header-Abhängigkeiten bestehen ... im Falle der Standardbibliothek aber sicherlich nicht nötig.


Eben.

Zitat von »"Deviloper"«


Zitat

Iteratoren
Wieviele Fälle würden denn spontan einfallen wo du die Matrix durch STL Algorithmen jagen würdest? Das sollte egtl der seltenste Fall sein.

count[_if](um bsw. bei einer matrix<int> gucken zu können wie oft 1 vorkommt), copy(falls man bsw. die Elemente einer Zeile in einen Vektor kopieren will ... warum auch immer ^^) usw. eigentlich könnte man die meisten Algorithmen dann dabei nutzen ... sicher ... es geht auch so ...


Naja, die Frage ist wie oft man das tatsächlich macht. Aber gegen Iteratoren spricht ja nichts, nur find ichs eher unnötig!

Edit: Achja: copy c'tor und assignment operator wären sinnvoll.
@D13_Dreinig

Werbeanzeige