Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

Tymczasowy obiekt klasy wewnatrz funkcji.

Ostatnio zmodyfikowano 2013-03-24 20:36
Autor Wiadomość
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.


P-78914
Monika90
» 2013-03-20 14:40:52
Jeżeli chodzi Ci o coś takiego:
C/C++
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.
P-78916
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 +:
C/C++
{
    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():
C/C++
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:

C/C++
Tablica Tablica::operator +( Tablica & b )
{
    int rB = b.rozmiar();
    int rA = rozmiar();
    int k =( rA > rB ) ? rA
        : rB; //r --> rozmiar wiekszej z dodawanych tablic
    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:

C/C++
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

P-78923
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.
P-79001
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.:

C/C++
CIntArray & CIntArray::operator =( const CIntArray & aTablica )

{
   
    // usuwamy naszą tablicę
   
    delete[] m_pnTablica;
   
   
    // alokujemy tyle pamięci, aby pomieścić przypisywaną tablicę
   
    m_uRozmiar = aTablica.m_uRozmiar;
   
    m_pnTablica = new int[ m_uRozmiar ];
   
   
    // kopiujemy tablicę
   
    memcpy( m_pnTablica, aTablica.m_pnTablica, m_uRozmiar * sizeof( int ) );
   
   
    // zwracamy wynik
   
    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.



P-79191
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.
P-79202
maze
Temat założony przez niniejszego użytkownika
» 2013-03-23 23:08:09
Ok, zrobilem to tak jak ponizej i dziala

C/C++
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; //k -> rozmiar wiekszej z tablic
    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 ] );
P-79267
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?
P-79273
« 1 » 2
  Strona 1 z 2 Następna strona