Konstruktor i destruktor z dynamiczną alokacją

Hipek
2011-12-23 10:04
Hipek
0

Witam.
Mam napisać program, który przy pomocy konstruktora stworzy dynamiczne pamięć a za pomocą destruktora zwolni ją.

Chciałbym Was zapytać, czy zrobiłem to dobrze:

 #include <iostream>
using namespace std;

class create
{
    private:
    int *wsk;
    public:
create(int ile)
{
wsk = new int(ile);

}
~create()
{
    delete wsk; // zwalnianie pamieci
}
void view()
{
    cout << *wsk << endl;
}

};

int main()
{
    int wielk;

cout << "Podaj wielkosc obiektu, ktory chcesz stworzyc: ";
cin >> wielk;

create obj(wielk); // tworze obiekt
obj.view(); //wyswietlam
obj.~create(); // kasowanie obiektu;

}

Proszę o ewentualne uwagi...
Nie jestem pewien czy dobrze to zrobiłem:

create(int ile)
{
wsk = new int(ile);

} 

Tutaj musi być ten nawias (ile) czy można to zrobić inaczej?

edytowany 1x, ostatnio: madmike, 2016-12-13 18:26

Pozostało 580 znaków

2011-12-23 10:29

Rejestracja: 9 lat temu

Ostatnio: 7 miesięcy temu

Lokalizacja: Kosmos

1

Zależy co chcesz zrobić. Chciałeś zarezerwować tyle pamięci ile ma parametr ile? Konstruktor int'a przyjmuje wartość jaką ma przybrać int po jego stworzeniu. Czyli linijka:

wsk = new int(10);

jest poprawna z tym, że rezerwujesz dla niej 4 bajty (int) i przypisujesz wartość 10.


Co kurła debuguj ten kod i streszczaj się klientowi chce się fixa, a jak nie kurła to odpale visuala i ci pomoge a tego byś nie chciał

Pozostało 580 znaków

Hipek
2011-12-23 10:32
Hipek
0

Tak, mam int przypisać. Czyli mogę tak do oddać?

Pozostało 580 znaków

2011-12-23 10:35

Rejestracja: 9 lat temu

Ostatnio: 7 miesięcy temu

Lokalizacja: Kosmos

0

Tak, możesz jeszcze wyzerować wskaźnik, dla ścisłości: wsk = 0;.


Co kurła debuguj ten kod i streszczaj się klientowi chce się fixa, a jak nie kurła to odpale visuala i ci pomoge a tego byś nie chciał

Pozostało 580 znaków

2011-12-23 13:12

Rejestracja: 9 lat temu

Ostatnio: 6 lat temu

0

Dlaczego jawnie wywołujesz destruktor? W twoim programie obj zostanie zniszczony dwa razy.

A nie jest tak, że jak sam sobie zabiję obiekt, to już dalej z nim się nic nie dzieje? - xeo545x39 2011-12-23 13:13
Jak alokujesz na stosie i obiekt wyjdzie z zasięgu, to masz zagwarantowane, że zostanie wywołany destruktor. Jeśli sam wywołasz go wcześniej, to masz dwa takie wywołania. - iooi 2011-12-23 13:21

Pozostało 580 znaków

2011-12-23 13:26

Rejestracja: 10 lat temu

Ostatnio: 6 dni temu

Lokalizacja: Redmond, WA

0

nie ma konstruktora kopiującego, przez co wywoływany jest automatyczny..
tutaj masz coś podobnego:
http://4programmers.net/Forum/C_i_C++/190622-operator_a_przypisanie?start=10


░█░█░█░█░█░█░█░█░█░█░█░
A na co mu ctor kopiujący? On ma napisać alokowanie i zwalnianie pamięci ;d - xeo545x39 2011-12-23 13:40
po to zeby nie uczyl sie zlych nawykow - krwq 2011-12-23 13:46

Pozostało 580 znaków

Hipek
2011-12-23 15:48
Hipek
0

Tak się dzieje, że sam sie usuwa? Przecież jak dwa razy wywołam ten obiekt bez użycia destruktora to on się wypisze... a jak użyje destruktora to nie.

Pozostało 580 znaków

2011-12-23 16:00

Rejestracja: 14 lat temu

Ostatnio: 1 godzina temu

Lokalizacja: Warszawa

0

Esencją destruktora jest fakt, że jest wywoływany automatycznie kiedy obiekt jest niszczony.


"Sugeruję wyobrazić sobie Słońce widziane z orbity Merkurego, a następnie dupę tej wielkości. W takiej właśnie dupie specjalista ma teksty o wspaniałej atmosferze, pracy pełnej wyzwań i tworzeniu innowacyjnych rozwiązań. Pracuje się po to, żeby zarabiać, a z resztą specjalista sobie poradzi we własnym zakresie, nawet jeśli firma mieści się w okopie na granicy obu Korei."
-somekind,
konkretny człowiek-konkretny przekaz :]
edytowany 2x, ostatnio: madmike, 2011-12-23 16:01

Pozostało 580 znaków

Hipek
2011-12-23 16:15
Hipek
0

To kiedy mój obiekt jest niszczony, skoro ja tego destruktora nie wywołuję?

Pozostało 580 znaków

2011-12-23 16:20

Rejestracja: 16 lat temu

Ostatnio: 2 dni temu

0

‌ Jeśli tworzysz obiekt na stosie (a nie na stercie czyli przez wskaźnik i new/delete), to obiekt jest niszczony w momencie, gdy „wylatuje z zasięgu”. W twoim przypadku nie trzeba wywoływać destruktora, bo i tak się wykona. Zobacz na ten przykład:

        int main()
        {
              create obj(wielk); // wywołanie konstruktora create::create(int)
              obj.view(); // ok

              if (true) // jakiś warunek, dla uproszczenia — zawsze prawdziwy
              {
                      create obj2 = obj; // wywołanie konstruktora kopiującego.
                                         // jeśli takiego nie ma, wywoła się domyślny,
                                         // który skopiuje tylko wskaźnik zamiast wszystkich wskazywanych danych.
                      obj2.view(); // ok
                      obj.view();  // ok
              } // skończył się zasięg zmiennej obj2. wykona się destruktor dla obj2, a w nim delete na wskaźniku.

              obj.view(); // BUM! odwołanie do wskaźnika tego samego, który został zwolniony w destruktorze obj2.
        } // skończył się zasięg zmiennej obj, wykona się destruktor.

‌ Rozwiązaniem są:

    a) zablokowanie konstruktora kopiującego i operatora kopiowania-przypisania, czyli zadeklarowanie ich jako prywatne (i nie definiowanie ich),
        private:
            create::create(const create&);
            create& operator=(const create&);
        wtedy niemożliwe staje się przypisanie obj2=obj.

    b) zdefiniowanie prawidłowych:
        public:

           create(const create& other)
           {
              // kopiowanie wszystkich pól o typach prostych:
              ile = other.ile; // musisz dodać to pole do klasy i wypełniać je w konstruktorze!

              // alokacja pamięci w nowym obiekcie:
              wsk = new int(ile);

              // kopiowanie właściwych danych:
              memcpy(wsk, other.wsk, ile * sizeof(int));
           }

           create& operator=(const create &other)
           {
               if (this != &other) // zabezpieczenie przed przypisaniem do samego siebie
               {
                 ile = other.ile; // j.w.
                 wsk = new int(ile);
                 memcpy(wsk, other.wsk, ile * sizeof(int));
               }
               return *this; // bo tak.
           }

‌ Tak, jest to upierdliwe — zwłaszcza w klasach, w których często dodajesz nowe pola. Wtedy trzeba pamiętać, by je dodać do tego konstruktora i operatora. Cóż, C++ to nie jest język w którym pisze się przyjemnie.

‌ Ja w przypadku większych klas przyjmuję punkt a), czyli zabraniam kopiowania, a operuję tylko na wskaźnikach (czyli u ciebie create *obj=new create(wielk), pamiętać o delete). Wtedy mój przykład będzie wyglądał tak:

        int main()
        {
              create *obj = new create(wielk); // wywołanie konstruktora create::create(int)
              obj.view(); // ok

              if (true)
              {
                      create *obj2 = obj; // tylko skopiowanie wskaźnika
                      obj2.view(); // ok
                      obj.view();  // ok
                      // delete obj2; // możemy to tu zrobić, ale nie musimy. jednak spowodowałoby to też zniszczenie obj.
              } // skończył się zasięg zmiennej obj2. nic się nie dzieje.

              obj.view(); // ok
              delete obj; // wywołanie destruktora.
        } // skończył się zasięg zmiennej obj, nic się nie dzieje (dlatego trzeba pamiętać o delete)

‌ Jak widać, w C++ obiekt albo sam się zniszczy, albo robimy to ręcznie, ale przez delete. Ręczne wywoływanie destruktora jest praktycznie niepotrzebne.

edytowany 6x, ostatnio: Azarien, 2011-12-23 16:31

Pozostało 580 znaków

2011-12-23 16:20

Rejestracja: 9 lat temu

Ostatnio: 6 lat temu

0

Gdy obiekt był na stosie, to jest niszczony jak wyjdzie z zakresu. W przypadku obiektów na stercie (alokowanych z użyciem new) destruktor wywoływany przy okazji delete.

Pozostało 580 znaków

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0