maze Temat założony przez niniejszego użytkownika |
Tymczasowy obiekt klasy wewnatrz funkcji. » 2013-03-20 14:34:32 Czesc mam takie pytanie do was,
Jezeli wewnatrz funkcji tworzymy obiekt i zwracamy go na koncu w postaci return;
To jak wyglada sprawa jego egzystencji, bo po wywolaniu funkcji powinien zostac usuniety gdyz opuszczamy zakres waznosci(funkcja) ale z drugiej strony go zwracamy.
Czy jak zwracamy obiekt w funkcji to nie zostaje on usuniety?? Destruktor nie jest wywolywany?
Jest to funkcja skladowa tej klasy.
|
|
Monika90 |
» 2013-03-20 14:40:52 Jeżeli chodzi Ci o coś takiego: struct X { };
X f() { X x; return x; }
int main() { X x = f(); }
to na zewnątrz (z funkcji f) zwrócona będzie kopia x, a sam x będzie zniszczony. Z tym że kompilator, tytułem optymalizacji, może pominąć kopiowanie i utworzyć x od razu w miejscu docelowym. |
|
maze Temat założony przez niniejszego użytkownika |
» 2013-03-20 15:35:59 Dzieki, o to mi chodzilo. Natomiast dalej mam gdzies blad i nie moge go zlokalizowac, wiem juz ze destruktor jest wywolywany dwukrotnie , czyli ewidentnie o jeden raz za duzo. Chce dodac dwie tablice do siebie, za pomoca przeladowanego operatora +: { system( "CLS" ); cout << "Dodamy do siebie dwie pierwsze tablice i zapiszemy w nowej\n"; cout << "Uzywamy przeladowanego operatora '+'\n\n"; int rA = baza[ 0 ]->rozmiar(); int rB = baza[ 1 ]->rozmiar(); dodaj_tablice(( rA > rB ) ? rA : rB ); * baza[ pnt - 1 ] = * baza[ 0 ] + * baza[ 1 ]; break; }
dodaj_tablice(): void dodaj_tablice( int n ) { int m = Tablica::ilosc; baza[ m ] = new Tablica( n ); if( baza[ m ] == NULL ) { cout << "\n\tBrak pamieci\n"; } }
przeladowany operator: Tablica Tablica::operator +( Tablica & b ) { int rB = b.rozmiar(); int rA = rozmiar(); int k =( rA > rB ) ? rA : rB; Tablica c( k, "temp" ); for( int i = 0; i < k; i++ ) { c.tab[ i ] =(( i >= rA ) ? 0 : tab[ i ] ) +(( i >= rB ) ? 0 : b.tab[ i ] ); } c.srednia(); return c; }
Konstruktory i Destruktor: Tablica::Tablica( int rozmiar ) { ilosc++; id = Tablica::ilosc; n = rozmiar; tab = new double[ n ]; nazwa = "Tablica"; nazwa += id; }
Tablica::Tablica( int rozmiar, char * name ) { ilosc++; id = Tablica::ilosc; n = rozmiar; tab = new double[ n ]; nazwa = name; }
Tablica::~Tablica() { cout << "\nDESTRUKOR: " << this->nazwa << endl; ilosc--; }
Kiedy uruchamiam switch case:5 widze na ekranie dwukrotne wywolanie destruktora dla Tablicy c (temp); A jak dodam delete[] tab do destruktora tak jak byc powinno, to normalnie moge usuwac tablice, i wszystko gra, ale jak chce je dodac switchem 5, to wywala debug error, ale nic mi on nie mowi. Moze ktos ma chwile zeby to roszyfrzyc, bo juz nie wiem co jest 5 |
|
Monika90 |
» 2013-03-21 08:11:32 Musisz zaimplementować konstruktor kopiujący i operator przypisania dla klasy Tablica. Bez tego nie zadziała poprawnie.
Dodam jeszcze, że sprawdzanie czy new zwróciło NULL nie ma sensu. New (a prznajmniej ta postać, której Ty używasz) zawsze zwraca prawidłowy wskaźnik do zaalokowanego obiektu, albo rzuca wyjątkiem. |
|
maze Temat założony przez niniejszego użytkownika |
» 2013-03-23 11:10:07 dzieki za naprowadzenie, wlasnie zglebiam szeroki temat i wdrazam implementacje. Po drodze mam pytanie; chodzi mi o zwracanie rezultatu przeladowanych operatorow, np.: CIntArray & CIntArray::operator =( const CIntArray & aTablica )
{ delete[] m_pnTablica; m_uRozmiar = aTablica.m_uRozmiar; m_pnTablica = new int[ m_uRozmiar ]; memcpy( m_pnTablica, aTablica.m_pnTablica, m_uRozmiar * sizeof( int ) ); return * this; } Jak wytlumaczyc koniecznosc zwracania wskaznika na obiekt przy tym operatorze? Jak wytlumaczyc ze raz zwracamy wskaznik a raz caly obiekt w zaleznosci od operatora? Nie moge wylapac tej roznicy. |
|
Monika90 |
» 2013-03-23 12:08:43 Tak się przyjęło, że operator = zwraca referencję do *this. Dzięki temu wielokrotne przypisanie a = b = c = d; działa wydajnie. Jakbyś zwracał obiekt przez wartość, to tworzone byłyby niepotrzebne kopie. Myślę, że generalnie należy zwracać referencję kiedy się da, a obiekt kiedy trzeba. A przedstawiony przez ciebie operator przypisania jest błędny, ponieważ nie działa poprawnie w przypadku samoprzypsania x = x; , oraz gdy new int[ m_uRozmiar ]; rzuci wyjątkiem. Najlepiej będzie, jak najpierw zaimplemetujesz kostruktor kopiujący, a potem za jego pomocą operator =, techniką copy-and-swap. |
|
maze Temat założony przez niniejszego użytkownika |
» 2013-03-23 23:08:09 Ok, zrobilem to tak jak ponizej i dziala Tablica::Tablica( const Tablica & kTablica ) : n( kTablica.rozmiar() ) { ilosc++; tab = new double[ n ]; memcpy( tab, kTablica.tab, n * sizeof( double ) ); srd = kTablica.srd; id = Tablica::ilosc; nazwa = "Tablica "; ostringstream id_temp; id_temp << id; nazwa.append( id_temp.str() ); cout << "\nKonstruktor kopiujacy " << nazwa << endl; }
Tablica & Tablica::operator +( const Tablica & b ) { int rB = b.rozmiar(); int rA = rozmiar(); int k =( rA > rB ) ? rA : rB; Tablica temp( k ); for( int i = 0; i < k; i++ ) { temp.tab[ i ] =(( i >= rA ) ? 0 : tab[ i ] ) +(( i >= rB ) ? 0 : b.tab[ i ] ); } temp.srednia(); return temp; }
Tablica Tablica::operator =( const Tablica & obiekt ) { if( & obiekt == this ) return * this; n = obiekt.rozmiar(); if( obiekt.n != n ) { delete[] tab; tab = new double[ n ]; } memcpy( adres(), obiekt.adres(), n * sizeof( double ) ); srd = obiekt.srd; return * this; }
* baza[ pnt - 1 ] =( * baza[ 0 ] + * baza[ 1 ] ); |
|
maze Temat założony przez niniejszego użytkownika |
» 2013-03-24 08:24:15 Chociaz w zasadzie nie rozumiem jednej rzeczy. Mianowicie, dlaczego uruchamia mi sie w takim wywolaniu najpierw konstruktor kopiujacy a pozniej dziala operator przypisania?
Skoro obiekt docelowy jest inicjalizowany wczesniej, to powinien uruchamiac sie sam operator przypisania, dlaczego wiec tak sie nie dzieje?
|
|
« 1 » 2 |