Více problémů s maticema – C / C++ – Fórum – Programujte.com
 x   TIP: Přetáhni ikonu na hlavní panel pro připnutí webu

Více problémů s maticema – C / C++ – Fórum – Programujte.comVíce problémů s maticema – C / C++ – Fórum – Programujte.com

 

Toto vlákno bylo označeno za vyřešené — příspěvek s řešením.
Sefiros0
Návštěvník
4. 5. 2013   #1
-
0
-

Hoj,

mám tady několik menších problémů a bohužel opravdu nevím jak na ně. První je v destruktoru třídy který mi odmítá uvolňovat paměť tak jak bych si představoval (furt mám memory leak) a druhý problém je s šablonovejma operátorovejma funkcema který mi při kompilaci házej chyby (něco se špatným použitím šablon).

Za pomoc budu vděčný neb už opravdu nemám nápady ani trpělivost to řešit  .

template <class T>
class matrix
{
    T **dataCore;
    int width;
    int height;
    bool fail;

    public:

    matrix(int width,int height);
    matrix(matrix<T> &givenMatrix);
    ~matrix();
    matrix& operator=(matrix<T> &givenMatrix);
    matrix operator+(matrix<T> &givenMatrix);
    int returnWidth() {return width;}
    int returnHeight() {return height;}
    bool isFail() {return fail;}
};

template <class T>
matrix<T>::matrix(int width,int height)
{
    dataCore = new T* [width];
    for (int i=0;i<width;++i)
    {
        dataCore[i] = new T [height];
    }
}

template <class T>
matrix<T>::matrix(matrix<T> &givenMatrix)
{
    this->~matrix();
    matrix(givenMatrix.returnWidth(),givenMatrix.returnHeight());
    for (int i=0;i < width;++i)
    {
        for (int y=0;y < height;++y)
        {
            dataCore[i][y] =  givenMatrix.dataCore[i][y];
        }
    }
}

template <class T>
matrix<T>::~matrix()
{
    for (int i=0;i < width;++i)
    {
       delete [] dataCore[i];
    }
    delete [] dataCore;
}

template <class T>
matrix& matrix<T>::operator=(matrix<T> &givenMatrix)
{
    matrix(givenMatrix);
    return *this;
}

template <class T>
matrix matrix<T>::operator+(matrix<T> &givenMatrix)
{
    if (width==givenMatrix.returnWidth() && height==givenMatrix.returnHeight() && this!=&givenMatrix)
    {
        matrix temp(width,height);
        for (int i=0;i < width;++i)
        {
            for (int y=0;y < height;++y)
            {
                temp.dataCore[i][y] =  dataCore[i][y] + givenMatrix.dataCore[i][y];
            }
        }
        return temp;
    }
    else
    {
        matrix temp(1,1);
        temp.fail=true;
        return temp;
    }
}
Nahlásit jako SPAM
IP: 80.188.252.–
KIIV
~ Moderátor
+43
God of flame
5. 5. 2013   #2
-
0
-

ja bych napady mel... pouzit v prve rade jednorozmerne pole...

a jako druhe treba vector... jen ho pak v konstruktoru inicializovat na spravnou velikost...

nejlepsi je, ze kdyz nebudes pouzivat pointer na vector, tak se sam zrusi na konci existence tridy

a pokud musis pouzit jen konkretne dynamicky pole, tak si hlavne ohlidat ruzny copy konstruktory a podobne + VYPISY co se zrovna deje!!!!!  hned uvidis, kolik tam mas konstruktoru, destruktoru, co se alokuje, co se likviduje

Nahlásit jako SPAM
IP: 94.113.92.–
Program vždy dělá to co naprogramujete, ne to co chcete...
KIIV
~ Moderátor
+43
God of flame
5. 5. 2013   #3
-
0
-

+ se mi zda docela blbej napad, volat destruktor nad this...

Nahlásit jako SPAM
IP: 94.113.92.–
Program vždy dělá to co naprogramujete, ne to co chcete...
vitamin+8
Grafoman
5. 5. 2013   #4
-
0
-

#1 Sefiros
 

#include <stdexcept>

template <class T>
matrix<T>	/*<-musis specifikovat aj template parameter navratoveho typu ak je definicia mimo triedy*/ 
matrix<T>::operator+(const /*<- parameter funkcie sa nebude menit*/ matrix<T> &x)const /*<- this funkcie sa nebude menit*/{
	
	//ak chces pouzivat konstruktory a operatory v ktorych moze nastat chyba, ale nemozes ju vratit ako navratovu hodnotu tak sa oplati pouzivat vynimky:
	if(width != x.width || height != x.height)throw std::logic_error("pokus o scitnie 2 matic s roznymi velkostami");
	    
	//this sa kludne moze rovnat parametru x:
	matrix temp(width,height);
	for(int i=0; i < width; ++i)
		for(int y=0;y < height;++y)
			temp.dataCore[i][y] =  dataCore[i][y] + x.dataCore[i][y];
		
	//treba mat copy construtor, idealne aj move constructor (c++11)
	return temp;
}

Ak pouzivas c++11, sprav aj move constructor kvoly tomu aby pri vracani matice nevznikali zbitocne kopie.

Ak nepozivas c++11, pretaz radsej matrix& operator+=(const matrix& ).

operator= mas ties zle.
 

Nahlásit jako SPAM
IP: 95.105.157.–
obfuscate: "The cruel god Malloc will strike you down. "
ZMeson: "That's the C god. C++ has a new god. "
Sefiros0
Návštěvník
5. 5. 2013   #5
-
0
-

Díky, už sem pochopil kde jsem s těma šablonama udělal kopanec a opravil jsem to. Výjimky v tomto případě nechci použít, ale chci vyzkoušet vytvořit konverzní funkci z matrix >> bool (jako u cin). Zbývá už jeden problém, mohl bych realizovat matici i pomocí vectoru a tím se zbavit problému s uvolňováním paměti, ale já osobně jsem si to chtěl zkusit realizovat pomocí pole. Způsob uvolnění mám úplně stejný jako na jedněch stránkách na netu a proto nechápu proč se děje problém.

 

template <class T>
matrix<T>::~matrix()
{
    for (int i=0;i < width;++i)
    {
       delete [] dataCore[i]; /* -> Tady mi to vždy shodí program */
    }
    delete [] dataCore;
}
Nahlásit jako SPAM
IP: 80.188.252.–
vitamin+8
Grafoman
5. 5. 2013   #6
-
0
-

#5 Sefiros
Pada ti to preto lebo rucne volas destructor tam kde nemas. 

Nahlásit jako SPAM
IP: 95.105.157.–
obfuscate: "The cruel god Malloc will strike you down. "
ZMeson: "That's the C god. C++ has a new god. "
ingiraxo+15
Grafoman
5. 5. 2013   #7
-
0
-

Tak jsem to zkusil opravit a nějak takto by to bylo.. skoro nic jsem neošetřoval, takže je to jen na oko 

template <class T>
class Matrix
{
public:
    Matrix();
    Matrix(const int width, const int height);
    Matrix(const Matrix<T>& mat);
    ~Matrix();

    void create(const int width, const int height);
    void copy(const Matrix<T>& mat);
    void set(const int x, const int y, const T value);
    T get(const int x, const int y) const;
    int getWidth() const;
    int getHeight() const;
    void show() const;

    Matrix& operator = (const Matrix<T>& mat);
    Matrix operator + (const Matrix<T>& mat);

private:
    T* data;
    int width;
    int height;
};

template <class T>
Matrix<T>::Matrix()
{
    data = NULL;
    width = 0;
    height = 0;
}

template <class T>
Matrix<T>::Matrix(const int width, const int height)
{
    data = NULL;
    create(width, height);
}

template <class T>
Matrix<T>::Matrix(const Matrix<T>& mat)
{
    data = NULL;
    copy(mat);
}

template <class T>
Matrix<T>::~Matrix()
{
    delete[] data;
}

template <class T>
void Matrix<T>::create(const int width, const int height)
{
    if (data)
        delete[] data;

    this->width = width;
    this->height = height;

    data = new T[width * height];
    memset(data, 0, sizeof(T) * width * height);
}

template <class T>
void Matrix<T>::copy(const Matrix<T>& mat)
{
    if (data)
        delete[] data;

    width = mat.width;
    height = mat.height;
    data = new T[width * height];

    memcpy(data, mat.data, sizeof(T) * width * height);
}

template <class T>
void Matrix<T>::set(const int x, const int y, const T value)
{
    *(data + x + y * width) = value;
}

template <class T>
T Matrix<T>::get(const int x, const int y) const
{
    return *(data + x + y * width);
}

template <class T>
int Matrix<T>::getWidth() const
{
    return width;
}

template <class T>
int Matrix<T>::getHeight() const
{
    return height;
}

template <class T>
void Matrix<T>::show() const
{
    for (int x = 0; x < width; ++x)
    {
        for (int y = 0; y < height; ++y)
        {
            cout << get(x, y) << "\t";
        }
        cout << endl;
    }
}

template <class T>
Matrix<T>& Matrix<T>::operator = (const Matrix<T>& mat)
{
    copy(mat);
    return *this;
}

template <class T>
Matrix<T> Matrix<T>::operator + (const Matrix<T>& mat)
{
    Matrix<T> temp(width, height);

    if (width == mat.width && height == mat.height)
    {
        for (int x = 0; x < width; ++x)
        {
            for (int y = 0; y < height; ++y)
            {
                T value = get(x, y) + mat.get(x, y);
                temp.set(x, y, value);
            }
        }
    }
    return temp;
}
Nahlásit jako SPAM
IP: 213.168.183.–
Moje aplikace: http://ophite.cz
Tutoriály na: C#
Sefiros0
Návštěvník
5. 5. 2013   #8
-
0
-

Velmi děkuji za veškerou pomoc, musím celou třídu kompletně předělat neb ji mám od základů blbě. Otázka na konec, používání konstruktorů a destruktorů v členských funkcích je špatně?

to ingiraxo: Děkuji za vytvoření kompletní třídy.


Nahlásit jako SPAM
IP: 80.188.252.–
vitamin+8
Grafoman
5. 5. 2013   #9
-
0
-

#8 Sefiros
Konstruktor sa vola pri vytvoreni triedy a destruktor sa vola ked objekt zanika.

V podstate pred volanim konstruktora obsahuje trieda nahodne data. Ty si zavolal destruktor na zaciatku construktora. Cize premenna 'dataCore' obsahovala nahodnu adresu a ty si s nou pracoval ako s dynamicky alkovanym polom.

Ty si pouzil na vytvorenie matice 2 rozmerne pole, s nim sa lepsie pracuje, ale dlhsie trva jeho vytvorenie a mazanie.

ingiraxo pouzil 1 rozmerne pole, to sa alokuje jednoduhsie (staci 1 new/delete), ale zas sa s nim horsie pracuje lebo musis vyratavat index podla velkosti matice a taky operator[] sa bude musiet riesit cez medzi triedu...

Obydva sposoby sa daju pouzit, kazdy ma vlastne vyhody/nevyhody. Ak si opravys chyby v tvojom kode tak to nemusis cele prerabat.

Nahlásit jako SPAM
IP: 95.105.157.–
obfuscate: "The cruel god Malloc will strike you down. "
ZMeson: "That's the C god. C++ has a new god. "
KIIV
~ Moderátor
+43
God of flame
5. 5. 2013   #10
-
0
-

+ kdyz zavolal destruktor nad vznikajicim objektem, tak to uz po sobe nemusi uvolnovat pamet, protoze uz zase neexistuje

Nahlásit jako SPAM
IP: 94.113.92.–
Program vždy dělá to co naprogramujete, ne to co chcete...
Sefiros0
Návštěvník
5. 5. 2013   #11
-
0
-

Tak sem udělal několik úprav takže už by mi to mělo fungovat, ale čelím zase jinému problému...mám poněkud zmatek v referencích a díky tomu mi hází kompilátor tuny chyb. Už sem si s tím ňákou dobu hrál a různě přidával či naopak ubíral z argumentů reference, ale jediný čeho sem tím dosáhnul byl měnící se počet chyb.

template <class T>
class Matrix
{
    T **dataCore;
    int width;
    int height;
    bool fail;
    ////////////////////////////////////////////////////////////
    void allocDataCore();
    void freeDataCore();
    void copyDataCore(Matrix<T> &target);
    ////////////////////////////////////////////////////////////
    public:
    ////////////////////////////////////////////////////////////
    Matrix(int m_width,int m_height);
    Matrix(Matrix<T> &givenMatrix);
    ~Matrix();
    ////////////////////////////////////////////////////////////
    Matrix<T> operator=(Matrix<T> givenMatrix);
    Matrix<T> operator+(Matrix<T> &givenMatrix);
    ////////////////////////////////////////////////////////////
    int returnWidth() {return width;}
    int returnHeight() {return height;}
    T& at(int m_width,int m_height);
    void fill(int &m_width,int &m_height,T value);
    ////////////////////////////////////////////////////////////
    operator bool() {return fail;}
};

////////////////////////////////////////////////////////////////
template <class T>
Matrix<T>::Matrix(int m_width,int m_height)
{
    width=m_width;
    height=m_height;
    fail=false;
    allocDataCore();
}

template <class T>
Matrix<T>::Matrix(Matrix<T> &givenMatrix)
{
    width=givenMatrix.width;
    height=givenMatrix.height;
    fail=givenMatrix.fail;
    allocDataCore();
    copyDataCore(givenMatrix);
}

template <class T>
Matrix<T>::~Matrix()
{
    freeDataCore();
}

template <class T>
void Matrix<T>::allocDataCore()
{
    dataCore = new T* [width];
    for (int i=0;i<width;++i)
    {
        dataCore[i] = new T [height];
    }
}

template <class T>
void Matrix<T>::freeDataCore()
{
    for (int i=0;i < width;++i)
    {
       delete [] dataCore[i];
    }
    delete [] dataCore;
}

template <class T>
void Matrix<T>::copyDataCore(Matrix<T> &target)
{
    for (int i=0;i < width;++i)
    {
        for (int y=0;y < height;++y)
        {
            dataCore[i][y] =  target.dataCore[i][y];
        }
    }
}
////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////
template <class T>
Matrix<T> Matrix<T>::operator=(Matrix<T> givenMatrix)
{
    if (this==&givenMatrix)
    return *this;
    freeDataCore();
    width=givenMatrix.width;
    height=givenMatrix.height;
    fail=givenMatrix.fail;
    allocDataCore();
    copyDataCore(givenMatrix);
    return *this;
}

template <class T>
Matrix<T> Matrix<T>::operator+(Matrix<T> &givenMatrix)
{
    if (width==givenMatrix.width && height==givenMatrix.height && this!=&givenMatrix)
    {
        Matrix temp(width,height);
        for (int i=0;i < width;++i)
        {
            for (int y=0;y < height;++y)
            {
                temp.dataCore[i][y] =  dataCore[i][y] + givenMatrix.dataCore[i][y];
            }
        }
        return temp;
    }
    else
    {
        Matrix temp(1,1);
        temp.fail=true;
        return temp;
    }
}

template <class T>
T& Matrix<T>::at(int m_width,int m_height)
{
    return dataCore[m_width][m_height];
}

template <class T>
void Matrix<T>::fill(int &m_width,int &m_height,T value)
{
    dataCore[m_width][m_height]=value;
}
////////////////////////////////////////////////////////////////
Nahlásit jako SPAM
IP: 80.188.252.–
KIIV
~ Moderátor
+43
God of flame
5. 5. 2013   #12
-
0
-

budes muset hodit i zpusob pouziti...  samo o sobe se to zkompilovat da v pohode

Nahlásit jako SPAM
IP: 94.113.92.–
Program vždy dělá to co naprogramujete, ne to co chcete...
Sefiros0
Návštěvník
5. 5. 2013   #13
-
0
-

tady je:

#include <iostream>
#include <cstdlib>

int main()
{
    using namespace std;
    Matrix<int> first(3,3);
    Matrix<int> second(first);

    cout << "FIRST: " << endl;
    for (int i=0;i<first.returnHeight();++i)
    {
        for (int y=0;y<first.returnWidth();++y)
        {
            first.fill(y,i,rand()%100);
        }
    }
    for (int i=0;i<first.returnHeight();++i)
    {
        for (int y=0;y<first.returnWidth();++y)
        {
            cout << first.at(y,i) << ", ";
        }
        cout << endl;
    }
    cout << "SECOND: " << endl;
    for (int i=0;i<second.returnHeight();++i)
    {
        for (int y=0;y<second.returnWidth();++y)
        {
            second.fill(y,i,rand()%100);
        }
    }
    for (int i=0;i<second.returnHeight();++i)
    {
        for (int y=0;y<second.returnWidth();++y)
        {
            cout << second.at(y,i) << ", ";
        }
        cout << endl;
    }

    Matrix<int> third(second);
    cout << "THIRD: " << endl;
    for (int i=0;i<third.returnHeight();++i)
    {
        for (int y=0;y<third.returnWidth();++y)
        {
            cout << third.at(y,i) << ", ";
        }
        cout << endl;
    }

    cout << "THIRD+FIRST: " << endl;
    third=third+first;
    for (int i=0;i<third.returnHeight();++i)
    {
        for (int y=0;y<third.returnWidth();++y)
        {
            cout << third.at(y,i) << ", ";
        }
        cout << endl;
    }
    return 0;
}
Nahlásit jako SPAM
IP: 80.188.252.–
Řešení
vitamin+8
Grafoman
5. 5. 2013   #14
-
0
-
Vyřešeno Nejlepší odpověď

#13 Sefiros
Akonahle funkcia vracia premennu, tak vratena premenna je rvalue. Ak chces vytvorit referenciu na rvalue tak ta referencia musi byt konstantna:

 
Tu mas moznosti kopirovacich konstruktorov (tvoja trieda moze mat aj vsetky 3):

//1.
Matrix(Matrix& m){/*...*/}	//ako parameter moze byt lvalue, co je hociaka premenna s menom alebo ina referencia

//2.
Matrix(const Matrix& m){/*...*/}	//ako parameter sa moze pouzit lvalue aj rvalue (rvalue su docasne premenne ako vysledok dakeho vyrazu, vratena premenna z funkcie, ...)

//3.
Matrix(Matrix&& m){/*...*/}	//ako parameter sa moze pouzit len rvalue

//vysledok tohto vyrazu je rvalue a ten moze byt skopyrovany len konstruktorom 2. a 3.
third+first;

edit:

Tvoj kod sa da o dost sprehladnit:

template <class T>
std::ostream& operator<<(std::ostream& out, Matrix<T>& m){
	for (int i=0;i<m.returnHeight();++i){
		for (int y=0;y<m.returnWidth();++y){
			out << m.at(y,i) << ", ";
		}
		out << std::endl;
	}
	return out;
}

template <class T>
Matrix<T> make_random_matrix(int r, int s){
	Matrix<T> m(r, s);
	
    for (int i=0;i<m.returnHeight();++i)
    {
        for (int y=0;y<m.returnWidth();++y)
        {
            m.fill(y,i,rand()%100);
        }
    }
    
    return m;
}

int main()
{
    using namespace std;
    
    Matrix<int> first = make_random_matrix<int>(3, 3);
    cout << "FIRST: " << endl << first << endl;

    Matrix<int> second = make_random_matrix<int>(3, 3);;	
    cout << "SECOND: " << endl << second << endl;
   
    Matrix<int> third = second;
    cout << "THIRD: " << endl << third << endl;

    third = third+first;
    cout << "THIRD+FIRST: " << endl << third << endl;

    return 0;
}

edit2:

Doporucujem ti vsade kde mozes davat const, napr:

template <class T>
class Matrix
{
	/*
	...
	 */
	
    //matica 'givenMatrix' sa nebude menit, tak ju oznac ako const
    Matrix(const Matrix<T> &givenMatrix);

    //matica 'givenMatrix' sa nebude menit, tak ju oznac ako const
    Matrix<T>& operator=(const Matrix<T> givenMatrix);
    
    //matica 'givenMatrix' sa nebude menit, tak ju oznac ako const
    //matica 'this' sa tiez nebude menit, tak oznac metodu ako const
    Matrix<T> operator+(const Matrix<T> &givenMatrix)const;

    //getery tiez oznac ako const:
    int returnWidth()const{return width;}
    int returnHeight()const{return height;}
    operator bool()const{return fail;}
    
    //verzia at() ktora umoznuje upravovat prvky v matici:
    T& at(int m_width,int m_height);
    
    //verzia at ktora neumoznuje upravovat prvky v matici
    const T& at(int m_width,int m_height)const;
    
};
Nahlásit jako SPAM
IP: 95.105.157.–
obfuscate: "The cruel god Malloc will strike you down. "
ZMeson: "That's the C god. C++ has a new god. "
Sefiros0
Návštěvník
5. 5. 2013   #15
-
0
-

to vitamin:

Skutečně děkuji za informace ohledně rvalue a lvalue, netušil jsem o co se jedná a že to může způsobit tolik problémů. Třída mi konečně kompletně funguje tak jak má, opravdu díky, bez rad bych to nedokončil. 

Nahlásit jako SPAM
IP: 80.188.252.–
Zjistit počet nových příspěvků

Přidej příspěvek

Toto téma je starší jak čtvrt roku – přidej svůj příspěvek jen tehdy, máš-li k tématu opravdu co říct!

Ano, opravdu chci reagovat → zobrazí formulář pro přidání příspěvku

×Vložení zdrojáku

×Vložení obrázku

Vložit URL obrázku Vybrat obrázek na disku
Vlož URL adresu obrázku:
Klikni a vyber obrázek z počítače:

×Vložení videa

Aktuálně jsou podporována videa ze serverů YouTube, Vimeo a Dailymotion.
×
 
Podporujeme Gravatara.
Zadej URL adresu Avatara (40 x 40 px) nebo emailovou adresu pro použití Gravatara.
Email nikam neukládáme, po získání Gravatara je zahozen.
-
Pravidla pro psaní příspěvků, používej diakritiku. ENTER pro nový odstavec, SHIFT + ENTER pro nový řádek.
Sledovat nové příspěvky (pouze pro přihlášené)
Sleduj vlákno a v případě přidání nového příspěvku o tom budeš vědět mezi prvními.
Reaguješ na příspěvek:

Uživatelé prohlížející si toto vlákno

Uživatelé on-line: 0 registrovaných, 39 hostů

Podobná vlákna

Hodně problemu — založil Jakub Kahoun

X problému, Y dotazů — založil Syslík

Fraktály - řešení problému — založil GoliathL

Riesenie problemu s obejktom — založil SVKSuli

Moderátoři diskuze

 

Hostujeme u Českého hostingu       ISSN 1801-1586       ⇡ Nahoru Webtea.cz logo © 20032024 Programujte.com
Zasadilo a pěstuje Webtea.cz, šéfredaktor Lukáš Churý